From cf7eafca1fbc9aae495d7b7d7e1fb4bc92e6819f Mon Sep 17 00:00:00 2001 From: Chris Xiong Date: Wed, 6 Apr 2016 09:46:52 +0800 Subject: Sometimes Naïve! MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ChangeLog | 3 + common/qmpmidiplay.cpp | 404 ++++++++++++++++ common/qmpmidiplay.hpp | 137 ++++++ common/qmpmidiread.cpp | 239 ++++++++++ main.cpp | 29 -- qdialskulpturestyle.cpp | 437 ----------------- qdialskulpturestyle.hpp | 39 -- qmidiplayer.pro | 74 +-- qmidiplayer.src.d/main.cpp | 29 ++ qmidiplayer.src.d/qdialskulpturestyle.cpp | 437 +++++++++++++++++ qmidiplayer.src.d/qdialskulpturestyle.hpp | 39 ++ qmidiplayer.src.d/qmpchanneleditor.cpp | 193 ++++++++ qmidiplayer.src.d/qmpchanneleditor.hpp | 42 ++ qmidiplayer.src.d/qmpchanneleditor.ui | 602 +++++++++++++++++++++++ qmidiplayer.src.d/qmpchannelswindow.cpp | 132 ++++++ qmidiplayer.src.d/qmpchannelswindow.hpp | 71 +++ qmidiplayer.src.d/qmpchannelswindow.ui | 146 ++++++ qmidiplayer.src.d/qmpefxwindow.cpp | 198 ++++++++ qmidiplayer.src.d/qmpefxwindow.hpp | 62 +++ qmidiplayer.src.d/qmpefxwindow.ui | 478 +++++++++++++++++++ qmidiplayer.src.d/qmphelpwindow.cpp | 31 ++ qmidiplayer.src.d/qmphelpwindow.hpp | 26 + qmidiplayer.src.d/qmphelpwindow.ui | 34 ++ qmidiplayer.src.d/qmpimidimapper.hpp | 16 + qmidiplayer.src.d/qmpinfowindow.cpp | 57 +++ qmidiplayer.src.d/qmpinfowindow.hpp | 24 + qmidiplayer.src.d/qmpinfowindow.ui | 91 ++++ qmidiplayer.src.d/qmpmainwindow.cpp | 510 ++++++++++++++++++++ qmidiplayer.src.d/qmpmainwindow.hpp | 90 ++++ qmidiplayer.src.d/qmpmainwindow.ui | 413 ++++++++++++++++ qmidiplayer.src.d/qmpplistwindow.cpp | 308 ++++++++++++ qmidiplayer.src.d/qmpplistwindow.hpp | 57 +++ qmidiplayer.src.d/qmpplistwindow.ui | 263 +++++++++++ qmidiplayer.src.d/qmppresetselect.cpp | 99 ++++ qmidiplayer.src.d/qmppresetselect.hpp | 36 ++ qmidiplayer.src.d/qmppresetselect.ui | 106 +++++ qmidiplayer.src.d/qmpsettingswindow.cpp | 289 ++++++++++++ qmidiplayer.src.d/qmpsettingswindow.hpp | 47 ++ qmidiplayer.src.d/qmpsettingswindow.ui | 761 ++++++++++++++++++++++++++++++ qmidiplayer.src.d/resources.qrc | 36 ++ qmidiplayerlite.pro | 24 + qmidiplayerlite.src.d/deployment.pri | 13 + qmidiplayerlite.src.d/main.cpp | 15 + qmidiplayerlite.src.d/main.qml | 144 ++++++ qmidiplayerlite.src.d/qml.qrc | 5 + qmidiplayerlite.src.d/qmpcorewrapper.hpp | 58 +++ qmidiplayerlite.src.d/qmpmidiplay.cpp | 406 ++++++++++++++++ qmidiplayerlite.src.d/qmpmidiplay.hpp | 137 ++++++ qmidiplayerlite.src.d/qmpmidiread.cpp | 240 ++++++++++ qmpchanneleditor.cpp | 193 -------- qmpchanneleditor.hpp | 42 -- qmpchanneleditor.ui | 602 ----------------------- qmpchannelswindow.cpp | 132 ------ qmpchannelswindow.hpp | 71 --- qmpchannelswindow.ui | 146 ------ qmpefxwindow.cpp | 198 -------- qmpefxwindow.hpp | 62 --- qmpefxwindow.ui | 478 ------------------- qmphelpwindow.cpp | 31 -- qmphelpwindow.hpp | 26 - qmphelpwindow.ui | 34 -- qmpimidimapper.hpp | 16 - qmpinfowindow.cpp | 57 --- qmpinfowindow.hpp | 24 - qmpinfowindow.ui | 91 ---- qmpmainwindow.cpp | 510 -------------------- qmpmainwindow.hpp | 90 ---- qmpmainwindow.ui | 413 ---------------- qmpmidiplay.cpp | 404 ---------------- qmpmidiplay.hpp | 137 ------ qmpmidiread.cpp | 239 ---------- qmpplistwindow.cpp | 308 ------------ qmpplistwindow.hpp | 57 --- qmpplistwindow.ui | 263 ----------- qmppresetselect.cpp | 99 ---- qmppresetselect.hpp | 36 -- qmppresetselect.ui | 106 ----- qmpsettingswindow.cpp | 289 ------------ qmpsettingswindow.hpp | 47 -- qmpsettingswindow.ui | 761 ------------------------------ resources.qrc | 36 -- 81 files changed, 7585 insertions(+), 6540 deletions(-) create mode 100644 common/qmpmidiplay.cpp create mode 100644 common/qmpmidiplay.hpp create mode 100644 common/qmpmidiread.cpp delete mode 100644 main.cpp delete mode 100644 qdialskulpturestyle.cpp delete mode 100644 qdialskulpturestyle.hpp create mode 100644 qmidiplayer.src.d/main.cpp create mode 100644 qmidiplayer.src.d/qdialskulpturestyle.cpp create mode 100644 qmidiplayer.src.d/qdialskulpturestyle.hpp create mode 100644 qmidiplayer.src.d/qmpchanneleditor.cpp create mode 100644 qmidiplayer.src.d/qmpchanneleditor.hpp create mode 100644 qmidiplayer.src.d/qmpchanneleditor.ui create mode 100644 qmidiplayer.src.d/qmpchannelswindow.cpp create mode 100644 qmidiplayer.src.d/qmpchannelswindow.hpp create mode 100644 qmidiplayer.src.d/qmpchannelswindow.ui create mode 100644 qmidiplayer.src.d/qmpefxwindow.cpp create mode 100644 qmidiplayer.src.d/qmpefxwindow.hpp create mode 100644 qmidiplayer.src.d/qmpefxwindow.ui create mode 100644 qmidiplayer.src.d/qmphelpwindow.cpp create mode 100644 qmidiplayer.src.d/qmphelpwindow.hpp create mode 100644 qmidiplayer.src.d/qmphelpwindow.ui create mode 100644 qmidiplayer.src.d/qmpimidimapper.hpp create mode 100644 qmidiplayer.src.d/qmpinfowindow.cpp create mode 100644 qmidiplayer.src.d/qmpinfowindow.hpp create mode 100644 qmidiplayer.src.d/qmpinfowindow.ui create mode 100644 qmidiplayer.src.d/qmpmainwindow.cpp create mode 100644 qmidiplayer.src.d/qmpmainwindow.hpp create mode 100644 qmidiplayer.src.d/qmpmainwindow.ui create mode 100644 qmidiplayer.src.d/qmpplistwindow.cpp create mode 100644 qmidiplayer.src.d/qmpplistwindow.hpp create mode 100644 qmidiplayer.src.d/qmpplistwindow.ui create mode 100644 qmidiplayer.src.d/qmppresetselect.cpp create mode 100644 qmidiplayer.src.d/qmppresetselect.hpp create mode 100644 qmidiplayer.src.d/qmppresetselect.ui create mode 100644 qmidiplayer.src.d/qmpsettingswindow.cpp create mode 100644 qmidiplayer.src.d/qmpsettingswindow.hpp create mode 100644 qmidiplayer.src.d/qmpsettingswindow.ui create mode 100644 qmidiplayer.src.d/resources.qrc create mode 100644 qmidiplayerlite.pro create mode 100644 qmidiplayerlite.src.d/deployment.pri create mode 100644 qmidiplayerlite.src.d/main.cpp create mode 100644 qmidiplayerlite.src.d/main.qml create mode 100644 qmidiplayerlite.src.d/qml.qrc create mode 100644 qmidiplayerlite.src.d/qmpcorewrapper.hpp create mode 100644 qmidiplayerlite.src.d/qmpmidiplay.cpp create mode 100644 qmidiplayerlite.src.d/qmpmidiplay.hpp create mode 100644 qmidiplayerlite.src.d/qmpmidiread.cpp delete mode 100644 qmpchanneleditor.cpp delete mode 100644 qmpchanneleditor.hpp delete mode 100644 qmpchanneleditor.ui delete mode 100644 qmpchannelswindow.cpp delete mode 100644 qmpchannelswindow.hpp delete mode 100644 qmpchannelswindow.ui delete mode 100644 qmpefxwindow.cpp delete mode 100644 qmpefxwindow.hpp delete mode 100644 qmpefxwindow.ui delete mode 100644 qmphelpwindow.cpp delete mode 100644 qmphelpwindow.hpp delete mode 100644 qmphelpwindow.ui delete mode 100644 qmpimidimapper.hpp delete mode 100644 qmpinfowindow.cpp delete mode 100644 qmpinfowindow.hpp delete mode 100644 qmpinfowindow.ui delete mode 100644 qmpmainwindow.cpp delete mode 100644 qmpmainwindow.hpp delete mode 100644 qmpmainwindow.ui delete mode 100644 qmpmidiplay.cpp delete mode 100644 qmpmidiplay.hpp delete mode 100644 qmpmidiread.cpp delete mode 100644 qmpplistwindow.cpp delete mode 100644 qmpplistwindow.hpp delete mode 100644 qmpplistwindow.ui delete mode 100644 qmppresetselect.cpp delete mode 100644 qmppresetselect.hpp delete mode 100644 qmppresetselect.ui delete mode 100644 qmpsettingswindow.cpp delete mode 100644 qmpsettingswindow.hpp delete mode 100644 qmpsettingswindow.ui delete mode 100644 resources.qrc diff --git a/ChangeLog b/ChangeLog index cfd9876..08e54ae 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,6 @@ +2016-04-06 0.7.0 beta +Merge qmidiplayerlite. Hope this won't break the repo. + 2016-04-05 0.7.0 beta Raise player thread priority in Windows. I've been so tired with the timing bug... diff --git a/common/qmpmidiplay.cpp b/common/qmpmidiplay.cpp new file mode 100644 index 0000000..6f69e33 --- /dev/null +++ b/common/qmpmidiplay.cpp @@ -0,0 +1,404 @@ +#include +#include +#include +#include +#include "qmpmidiplay.hpp" +#ifdef _WIN32 +#include +uint64_t pf; +#endif +void CMidiPlayer::fluidPreInitialize() +{ + settings=new_fluid_settings(); +} +void CMidiPlayer::fluidInitialize() +{ + synth=new_fluid_synth(settings); + adriver=new_fluid_audio_driver(settings,synth); + fluid_synth_set_chorus(synth,FLUID_CHORUS_DEFAULT_N,FLUID_CHORUS_DEFAULT_LEVEL, + FLUID_CHORUS_DEFAULT_SPEED,FLUID_CHORUS_DEFAULT_DEPTH, + FLUID_CHORUS_DEFAULT_TYPE); +#ifndef _WIN32 + if(!singleInstance) + { + if(midiFile->getStandard()==4) + fluid_synth_set_channel_type(synth,9,CHANNEL_TYPE_MELODIC); + else if(midiFile->getStandard()==1) + fluid_synth_set_channel_type(synth,9,CHANNEL_TYPE_DRUM); + else + { + fluid_synth_set_channel_type(synth,9,CHANNEL_TYPE_DRUM); + fluid_synth_bank_select(synth,9,128); + } + } +#endif +} +void CMidiPlayer::fluidDeinitialize() +{ + if(!synth||!adriver||!settings)return; + delete_fluid_settings(settings); + delete_fluid_audio_driver(adriver); + delete_fluid_synth(synth); + settings=NULL;synth=NULL;adriver=NULL; +} +void CMidiPlayer::processEvent(const SEvent *e) +{ + switch(e->type&0xF0) + { + case 0x80://Note off + fluid_synth_noteoff(synth,e->type&0x0F,e->p1); + break; + case 0x90://Note on + if((mute>>(e->type&0x0F))&1)break;//muted + if(solo&&!((solo>>(e->type&0x0F))&1))break; + fluid_synth_noteon(synth,e->type&0x0F,e->p1,e->p2); + break; + case 0xB0://CC + if(e->p1==100)rpnid=e->p2; + if(e->p1==6)rpnval=e->p2; + if(~rpnid&&~rpnval) + { + if(rpnid==0)fluid_synth_pitch_wheel_sens(synth,e->type&0x0F,rpnval); + rpnid=rpnval=-1; + } + fluid_synth_cc(synth,e->type&0x0F,e->p1,e->p2); + break; + case 0xC0://PC + fluid_synth_program_change(synth,e->type&0x0F,e->p1); + break; + case 0xE0://PW + fluid_synth_pitch_bend(synth,e->type&0x0F,e->p1); + break; + case 0xF0://Meta/SysEx + if((e->type&0x0F)==0x0F) + { + switch(e->p1) + { + case 0x51: + ctempo=e->p2;dpt=ctempo*1000/divs; + break; + case 0x58: + ctsn=e->p2>>24; + ctsd=1<<((e->p2>>16)&0xFF); + break; + case 0x59: + cks=e->p2; + break; + case 0x01:case 0x02:case 0x03: + case 0x04:case 0x05:case 0x06: + case 0x07: + //if(e->str)puts(e->str); + break; + } + } + if((e->type&0x0F)==0x00||(e->type&0x0F)==07) + { + int io=0; + if(sendSysEx)fluid_synth_sysex(synth,e->str,e->p1,NULL,&io,NULL,0); + } + break; + } +} +void CMidiPlayer::processEventStub(const SEvent *e) +{ + switch(e->type&0xF0) + { + case 0xB0://CC + if(e->p1==100)rpnid=e->p2; + if(e->p1==6)rpnval=e->p2; + if(~rpnid&&~rpnval) + { + if(rpnid==0)ccc[e->type&0x0F][134]=rpnval; + rpnid=rpnval=-1; + } + ccc[e->type&0x0F][e->p1]=e->p2; + break; + case 0xC0://PC + ccc[e->type&0x0F][128]=e->p1; + break; + case 0xD0://CP + ccc[e->type&0x0F][129]=e->p1; + break; + case 0xE0://PW + ccc[e->type&0x0F][130]=e->p1; + break; + case 0xF0://Meta/SysEx + if((e->type&0x0F)==0x0F) + { + switch(e->p1) + { + case 0x51: + ctempo=e->p2;dpt=ctempo*1000/divs; + ccc[0][131]=dpt; + break; + case 0x58: + ccc[0][132]=e->p2; + break; + case 0x59: + ccc[0][133]=e->p2; + break; + } + } + break; + } +} +#ifdef _WIN32 +void w32usleep(uint64_t t) +{ + uint64_t st=0,ct=0; + timeBeginPeriod(1); + QueryPerformanceCounter((LARGE_INTEGER*)&st); + do{ + if(t>10000+(ct-st)*1000000/pf)Sleep((t-(ct-st)*1000000/pf)/2000); + else if(t>5000+(ct-st)*1000000/pf)Sleep(1); + else std::this_thread::yield(); + QueryPerformanceCounter((LARGE_INTEGER*)&ct); + }while((ct-st)*1000000getEvent(0)->time;tceptrgetEventCount();) + { + while(tcpaused)std::this_thread::sleep_for(std::chrono::milliseconds(100)); + while(!tcstop&&midiFile&&tceptrgetEventCount()&&ct==midiFile->getEvent(tceptr)->time) + processEvent(midiFile->getEvent(tceptr++)); + if(tcstop||!midiFile||tceptr>=midiFile->getEventCount())break; + if(resumed)resumed=false; + else +#if 0 + w32usleep((midiFile->getEvent(tceptr)->time-ct)*(dpt/1000)); +#else + std::this_thread::sleep_for(std::chrono::nanoseconds(midiFile->getEvent(tceptr)->time-ct)*dpt); +#endif + if(tcstop||!midiFile)break; + ct=midiFile->getEvent(tceptr)->time; + } + while(!tcstop&&synth&&(waitvoice&&fluid_synth_get_active_voice_count(synth)>0))std::this_thread::sleep_for(std::chrono::milliseconds(2)); + finished=1; +} +void CMidiPlayer::fileTimer1Pass() +{ + ftime=.0;ctempo=0x7A120;dpt=ctempo*1000/divs; + for(uint32_t eptr=0,ct=midiFile->getEvent(0)->time;eptrgetEventCount();) + { + while(eptrgetEventCount()&&ct==midiFile->getEvent(eptr)->time) + processEventStub(midiFile->getEvent(eptr++)); + if(eptr>=midiFile->getEventCount())break; + ftime+=(midiFile->getEvent(eptr)->time-ct)*dpt/1e9; + ct=midiFile->getEvent(eptr)->time; + } +} +void CMidiPlayer::fileTimer2Pass() +{ + double ctime=.0;uint32_t c=1;ctempo=0x7A120;dpt=ctempo*1000/divs; + memset(stamps,0,sizeof(stamps));memset(ccstamps,0,sizeof(ccstamps)); + memset(ccc,0,sizeof(ccc));rpnid=rpnval=-1;for(int i=0;i<16;++i) + { + ccc[i][7]=100;ccc[i][10]=64;ccc[i][11]=127; + 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; + ccc[0][131]=dpt;ccc[0][132]=0x04021808; + ccc[0][133]=0;ccc[0][134]=2; + }if(midiFile->getStandard()!=4)ccc[9][0]=128; + for(int i=0;i<16;++i)for(int j=0;j<135;++j) + ccstamps[0][i][j]=ccc[i][j]; + for(uint32_t eptr=0,ct=midiFile->getEvent(0)->time;eptrgetEventCount();) + { + while(eptrgetEventCount()&&ct==midiFile->getEvent(eptr)->time) + processEventStub(midiFile->getEvent(eptr++)); + if(eptr>=midiFile->getEventCount())break; + ctime+=(midiFile->getEvent(eptr)->time-ct)*dpt/1e9; + while(ctime>ftime*c/100.) + { + for(int i=0;i<16;++i)for(int j=0;j<135;++j) + ccstamps[c][i][j]=ccc[i][j]; + stamps[c++]=eptr; + if(c>100)break; + } + ct=midiFile->getEvent(eptr)->time; + } + while(c<101) + { + for(int i=0;i<16;++i)for(int j=0;j<135;++j) + ccstamps[c][i][j]=ccc[i][j]; + stamps[c++]=midiFile->getEventCount(); + } +} +CMidiPlayer::CMidiPlayer(bool singleInst) +{ + midiFile=NULL;resumed=false;singleInstance=singleInst; + settings=NULL;synth=NULL;adriver=NULL;waitvoice=true; +#ifdef _WIN32 + QueryPerformanceFrequency((LARGE_INTEGER*)&pf); +#endif +} +CMidiPlayer::~CMidiPlayer() +{ + if(singleInstance)fluidDeinitialize(); +} +void CMidiPlayer::playerPanic(bool reset) +{ + if(reset)for(int i=0;i<16;++i) + { + fluid_synth_pitch_bend(synth,i,8192); + fluid_synth_cc(synth,i,7,100); + fluid_synth_cc(synth,i,10,64); + fluid_synth_cc(synth,i,11,127); + } + for(int i=0;i<16;++i)fluid_synth_all_notes_off(synth,i); +} +bool CMidiPlayer::playerLoadFile(const char* fn) +{ + midiFile=new CMidiFile(fn); + if(!midiFile->isValid())return false; + divs=midiFile->getDivision(); + fileTimer1Pass(); + fileTimer2Pass(); + return true; +} +void CMidiPlayer::playerInit() +{ + ctempo=0x7A120;ctsn=4;ctsd=4;cks=0;dpt=ctempo*1000/divs; + tceptr=0;tcstop=0;tcpaused=0;finished=0;mute=solo=0; + sendSysEx=true;rpnid=rpnval=-1; + if(!singleInstance)fluidPreInitialize(); +} +void CMidiPlayer::playerDeinit() +{ + tceptr=0;tcstop=1;tcpaused=0; + delete midiFile;midiFile=NULL; + if(!singleInstance)fluidDeinitialize(); +} +void CMidiPlayer::playerThread() +{ + playEvents(); +} + +void CMidiPlayer::rendererLoadFile(const char* ofn) +{ + settings=new_fluid_settings(); + fluid_settings_setstr(settings,"audio.file.name",ofn); +} +void CMidiPlayer::rendererInit(const char* fn) +{ + finished=0; + synth=new_fluid_synth(settings); + player=new_fluid_player(synth); + fluid_player_add(player,fn); +} +void CMidiPlayer::rendererThread() +{ + fluid_file_renderer_t* renderer=new_fluid_file_renderer(synth); + fluid_player_play(player); + while(fluid_player_get_status(player)==FLUID_PLAYER_PLAYING) + if(fluid_file_renderer_process_block(renderer)!=FLUID_OK)break; + delete_fluid_file_renderer(renderer); + finished=1; +} +void CMidiPlayer::rendererDeinit() +{ + delete_fluid_player(player); + delete_fluid_synth(synth); + delete_fluid_settings(settings); + player=NULL;synth=NULL;settings=NULL; +} + +void CMidiPlayer::sendSysX(bool send){sendSysEx=send;} +uint32_t CMidiPlayer::getStamp(int id){return stamps[id];} +uint32_t CMidiPlayer::getTCeptr(){return tceptr;} +void CMidiPlayer::setTCeptr(uint32_t ep,uint32_t st) +{ + resumed=true; + if(ep==midiFile->getEventCount())tcstop=1;else tceptr=ep; + for(int i=0;i<16;++i) + { + for(int j=0;j<120;++j)fluid_synth_cc(synth,i,j,ccstamps[st][i][j]); + fluid_synth_program_change(synth,i,ccstamps[st][i][128]); + //fluid_synth_pitch_bend(synth,i,ccstamps[st][i][130]); + dpt=ccstamps[st][0][131];ctempo=dpt*divs/1000; + ctsn=ccstamps[st][0][132]>>24;ctsd=1<<((ccstamps[st][0][132]>>16)&0xFF); + cks=ccstamps[st][0][133]; + } +} +double CMidiPlayer::getFtime(){return ftime;} +void CMidiPlayer::getCurrentTimeSignature(int *n,int *d){*n=ctsn;*d=ctsd;} +void CMidiPlayer::getCurrentKeySignature(int *ks){*ks=cks;} +uint32_t CMidiPlayer::getFileNoteCount(){return midiFile?midiFile->getNoteCount():0;} +uint32_t CMidiPlayer::getFileStandard(){return midiFile?midiFile->getStandard():0;} +const char* CMidiPlayer::getTitle(){return midiFile?midiFile->getTitle():"";} +const char* CMidiPlayer::getCopyright(){return midiFile?midiFile->getCopyright():"";} +double CMidiPlayer::getTempo(){return 60./(ctempo/1e6)/**ctsd/4.*/;} +uint32_t CMidiPlayer::getTCpaused(){return tcpaused;} +void CMidiPlayer::setTCpaused(uint32_t ps){tcpaused=ps;} +uint32_t CMidiPlayer::isFinished(){return finished;} +void CMidiPlayer::setResumed(){resumed=true;} +void CMidiPlayer::setWaitVoice(bool wv){waitvoice=wv;} +void CMidiPlayer::setGain(double gain){if(settings)fluid_settings_setnum(settings,"synth.gain",gain);} +int CMidiPlayer::getPolyphone(){return synth?fluid_synth_get_active_voice_count(synth):0;} +int CMidiPlayer::getMaxPolyphone(){return synth?fluid_synth_get_polyphony(synth):0;} +void CMidiPlayer::setMaxPolyphone(int p){if(synth)fluid_synth_set_polyphony(synth,p);} + +void CMidiPlayer::getChannelPreset(int ch,int *b,int *p,char *name) +{ + if(!synth)return(void)(b=0,p=0,strcpy(name,"")); + fluid_synth_channel_info_t info; + fluid_synth_get_channel_info(synth,ch,&info); + *b=info.bank;*p=info.program; + strcpy(name,info.name); +} +void CMidiPlayer::setChannelPreset(int ch,int b,int p) +{ + if(!synth)return; + fluid_synth_bank_select(synth,ch,b); + fluid_synth_program_change(synth,ch,p); +} +//16MSB..LSB1 +void CMidiPlayer::setBit(uint16_t &n, uint16_t bn, uint16_t b) +{n^=(-b^n)&(1< +#include +#include +#include +struct SEvent +{ + uint32_t iid,time,p1,p2; + uint8_t type; + char *str; + SEvent(){time=p1=p2=0;type=0;str=NULL;} + SEvent(uint32_t _iid,uint32_t _t,char _tp,uint32_t _p1,uint32_t _p2,const char* s=NULL) + { + iid=_iid;time=_t;type=_tp; + p1=_p1;p2=_p2; + if(s){str=new char[strlen(s)+2];strcpy(str,s);}else str=NULL; + } +}; +class CMidiFile +{ + private: + SEvent *eventList[10000000]; + char *title,*copyright; + uint32_t eventc,std;//standard 0=? 1=GM 2=GM2 3=GS 4=XG + uint32_t fmt,trk,divs; + FILE *f; + int byteread,valid; + uint32_t notes,curt,curid; + + void error(int fatal,const char* format,...); + uint32_t readSW(); + uint32_t readDW(); + uint32_t readVL(); + int eventReader(); + void trackChunkReader(); + void headerChunkReader(); + int chunkReader(int hdrXp); + public: + CMidiFile(const char* fn); + ~CMidiFile(); + const SEvent* getEvent(uint32_t id); + uint32_t getEventCount(); + uint32_t getDivision(); + uint32_t getNoteCount(); + uint32_t getStandard(); + const char* getTitle(); + const char* getCopyright(); + bool isValid(); +}; +class CMidiPlayer +{ + private: + CMidiFile *midiFile; + uint32_t stamps[101]; + uint32_t ccstamps[101][16][135],ccc[16][135]; + //0..127:cc 128:pc 129:cp 130:pb 131:tempo 132:ts 133:ks 134:pbr + int32_t rpnid,rpnval; + uint16_t mute,solo; + double ftime; + bool sendSysEx,singleInstance,waitvoice; + fluid_settings_t* settings; + fluid_synth_t* synth; + fluid_audio_driver_t* adriver; + fluid_player_t* player; + uint32_t ctempo,ctsn,ctsd,dpt,divs,cks; + //raw tempo, timesig num., timesig den., delay per tick, division, keysig + //thread control + uint32_t tceptr,tcpaused,tcstop; + uint32_t finished,resumed; + + void setBit(uint16_t &n,uint16_t bn,uint16_t b); + void processEvent(const SEvent *e); + void processEventStub(const SEvent *e); + void playEvents(); + void fileTimer1Pass(); + void fileTimer2Pass(); + public: + CMidiPlayer(bool singleInst=false); + ~CMidiPlayer(); + bool playerLoadFile(const char* fn); + void playerInit(); + void fluidPreInitialize(); + void fluidInitialize(); + void fluidDeinitialize(); + void playerDeinit(); + void playerThread(); + void playerPanic(bool reset=false); + + void rendererLoadFile(const char* ofn); + void rendererInit(const char *fn); + void rendererThread(); + void rendererDeinit(); + + //playing control methods + uint32_t getStamp(int id); + uint32_t getTCeptr(); + void setTCeptr(uint32_t ep,uint32_t st); + uint32_t getTCpaused(); + void setTCpaused(uint32_t ps); + uint32_t isFinished(); + void setResumed(); + void setWaitVoice(bool wv); + + double getFtime(); + void getCurrentTimeSignature(int *n,int *d); + void getCurrentKeySignature(int *ks); + uint32_t getFileNoteCount(); + uint32_t getFileStandard(); + double getTempo(); + const char* getTitle(); + const char* getCopyright(); + + void setGain(double gain); + void sendSysX(bool send); + int getPolyphone(); + int getMaxPolyphone(); + void setMaxPolyphone(int p); + + 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); + int getCC(int ch,int id); + void setCC(int ch,int id,int val); + void getReverbPara(double *r,double *d,double *w,double *l); + void setReverbPara(int e,double r,double d,double w,double l); + void getChorusPara(int *fb,double *l,double *r,double *d,int *type); + void setChorusPara(int e,int fb,double l,double r,double d,int type); + + fluid_settings_t* getFluidSettings(); + void pushSoundFont(const char* sf); + int getSFCount(); + fluid_sfont_t* getSFPtr(int sfid); +}; +#endif diff --git a/common/qmpmidiread.cpp b/common/qmpmidiread.cpp new file mode 100644 index 0000000..fd2e0d9 --- /dev/null +++ b/common/qmpmidiread.cpp @@ -0,0 +1,239 @@ +//CLI Midi file player based on libfluidsynth +//Midi file reading module +//Written by Chris Xiong, 2015 +#include +#include +#include +#include +#include +#include +#include "qmpmidiplay.hpp" +const char* GM1SysX={"\xF0\x7E\x7F\x09\x01\xF7"}; +const char* GM2SysX={"\xF0\x7E\x7F\x09\x03\xF7"}; +const char* GSSysEx={"\xF0\x41\x10\x42\x12\x40\x00\x7F\x00\x41\xF7"}; +const char* XGSysEx={"\xF0\x43\x10\x4C\x00\x00\x7E\x00\xF7"}; +bool cmp(SEvent *a,SEvent *b){return a->time-b->time?a->timetime:a->iidiid;} +void CMidiFile::error(int fatal,const char* format,...) +{ + va_list ap; + va_start(ap,format);vfprintf(stderr,format,ap);va_end(ap); + fprintf(stderr," at %#lx\n",ftell(f)); + if(fatal)throw 2; +} +uint32_t CMidiFile::readSW() +{ + byteread+=2; + uint32_t ret=0; + for(int i=0;i<2;++i){ret<<=8;ret|=((uint32_t)fgetc(f))&0xFF;} + return ret; +} +uint32_t CMidiFile::readDW() +{ + byteread+=4; + uint32_t ret=0; + for(int i=0;i<4;++i){ret<<=8;ret|=((uint32_t)fgetc(f))&0xFF;} + return ret; +} +uint32_t CMidiFile::readVL() +{ + uint32_t ret=0,t,c=0; + do + { + t=fgetc(f); + if(++c>4)error(1,"E: Variable length type overflow."); + ret<<=7;ret|=(t&0x7F); + }while(t&0x80); + byteread+=c; + return ret; +} +int CMidiFile::eventReader()//returns 0 if End of Track encountered +{ + uint32_t delta=readVL();curt+=delta; + char type=fgetc(f);++byteread;uint32_t p1,p2; + static char lasttype; +retry: + switch(type&0xF0) + { + case 0x80://Note Off + p1=fgetc(f);p2=fgetc(f);byteread+=2; + eventList[eventc++]=new SEvent(curid,curt,type,p1,p2); + break; + case 0x90://Note On + p1=fgetc(f);p2=fgetc(f);byteread+=2; + if(p2) + { + ++notes; + eventList[eventc++]=new SEvent(curid,curt,type,p1,p2); + } + else + eventList[eventc++]=new SEvent(curid,curt,(type&0x0F)|0x80,p1,p2); + break; + case 0xA0://Note Aftertouch + p1=fgetc(f);p2=fgetc(f);byteread+=2; + eventList[eventc++]=new SEvent(curid,curt,type,p1,p2); + break; + case 0xB0://Controller Change + p1=fgetc(f);p2=fgetc(f);byteread+=2; + eventList[eventc++]=new SEvent(curid,curt,type,p1,p2); + break; + case 0xC0://Patch Change + p1=fgetc(f);++byteread; + eventList[eventc++]=new SEvent(curid,curt,type,p1,0); + break; + case 0xD0://Channel Aftertouch + p1=fgetc(f);++byteread; + eventList[eventc++]=new SEvent(curid,curt,type,p1,0); + break; + case 0xE0://Pitch wheel + p1=fgetc(f);p2=fgetc(f);byteread+=2; + eventList[eventc++]=new SEvent(curid,curt,type,(p1|(p2<<7))&0x3FFF,0); + break; + case 0xF0: + if((type&0x0F)==0x0F)//Meta Event + { + char metatype=fgetc(f);++byteread; + switch(metatype) + { + case 0x00://Sequence Number + fgetc(f);fgetc(f);fgetc(f); + byteread+=3; + break; + case 0x20://Channel Prefix + fgetc(f);fgetc(f);byteread+=2; + break; + case 0x2F://End of Track + fgetc(f);++byteread; + return 0; + break; + case 0x51://Set Tempo + p1=readDW();p1&=0x00FFFFFF; + eventList[eventc++]=new SEvent(curid,curt,type,metatype,p1); + break; + case 0x54://SMTPE offset, not handled. + fgetc(f);fgetc(f);fgetc(f); + fgetc(f);fgetc(f);fgetc(f); + byteread+=6; + break; + case 0x58://Time signature + fgetc(f);++byteread; + p1=readDW(); + eventList[eventc++]=new SEvent(curid,curt,type,metatype,p1); + break; + case 0x59://Key signature + fgetc(f);++byteread; + p1=readSW(); + eventList[eventc++]=new SEvent(curid,curt,type,metatype,p1); + break; + case 0x01:case 0x02:case 0x03: + case 0x04:case 0x05:case 0x06: + case 0x07:case 0x7F:default://text-like meta + { + uint32_t len=readVL(),c;char* str=NULL; + if(len<=1024&&len>0)str=new char[len+8]; + for(c=0;c0)delete[] str; + } + } + } + else if((type&0x0F)==0x00||(type&0x0F)==0x07)//SysEx + { + uint32_t len=readVL(),c;char* str=NULL; + str=new char[len+8]; + if((type&0x0F)==0x00) + { + str[0]=0xF0;++len; + for(c=1;cchnklen) + { + error(1,"E: Read past end of track."); + }*/ +} +void CMidiFile::headerChunkReader() +{ + int chnklen=readDW();byteread=0; + if(chnklen<6)error(1,"E: Header chunk too short."); + if(chnklen>6)error(0,"W: Header chunk length longer than expected. Ignoring extra bytes."); + fmt=readSW();trk=readSW();divs=readSW(); + if(divs&0x8000)error(1,"E: SMTPE format is not supported."); + for(;byteread0;--chnklen)fgetc(f);return 0; + } + else return trackChunkReader(),1; +} +CMidiFile::CMidiFile(const char* fn) +{ + title=copyright=NULL;notes=eventc=0;std=0;valid=1; + try + { + if(!(f=fopen(fn,"rb")))throw (fprintf(stderr,"E: file %s doesn't exist!\n",fn),2); + chunkReader(1); + for(uint32_t i=0;i. - */ -#include "qmpmainwindow.hpp" -#include -#include - -int main(int argc,char **argv) -{ - QApplication a(argc,argv); - qmpMainWindow w; - if(w.pharseArgs(argc,argv)==1)return 0; - - return a.exec(); -} diff --git a/qdialskulpturestyle.cpp b/qdialskulpturestyle.cpp deleted file mode 100644 index 7c181a0..0000000 --- a/qdialskulpturestyle.cpp +++ /dev/null @@ -1,437 +0,0 @@ -/****************************************************************************** - - Skulpture - Classical Three-Dimensional Artwork for Qt 4 - - Copyright (c) 2007-2009 Christoph Feck - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -*****************************************************************************/ -#include -#include -#include -#include - -#include "qdialskulpturestyle.hpp" - -#ifndef M_PI -#define M_PI 3.141592653589793f -#endif - -static const bool UsePixmapCache = true; - -static void -paintIndicatorCached(QPainter *painter, const QStyleOption *option, void (*paintIndicator)(QPainter *painter, const QStyleOption *option), bool useCache, const QString &pixmapName) -{ - QPixmap pixmap; - - if (!useCache || !QPixmapCache::find(pixmapName, pixmap)) { - pixmap = QPixmap(option->rect.size()); -#if 1 - pixmap.fill(Qt::transparent); - // pixmap.fill(Qt::red); -#else - pixmap.fill(option->palette.color(QPalette::Window)); -#endif - QPainter p(&pixmap); - QStyleOption opt = *option; - opt.rect = QRect(QPoint(0, 0), option->rect.size()); - // p.setCompositionMode(QPainter::CompositionMode_Clear); - // p.setCompositionMode(QPainter::CompositionMode_Source); - // p.fillRect(opt.rect, Qt::transparent); - // p.setCompositionMode(QPainter::CompositionMode_SourceOver); - p.setFont(painter->font()); - p.setRenderHint(QPainter::Antialiasing, true); - paintIndicator(&p, &opt); - p.end(); - if (useCache) { - QPixmapCache::insert(pixmapName, pixmap); - // qDebug() << "inserted into cache:" << pixmapName; - } - } - painter->drawPixmap(option->rect, pixmap); -} - -void -paintDialBase(QPainter *painter, const QStyleOption *option) -{ -// painter->fillRect(option->rect, Qt::red); -// painter->save(); -// painter->setRenderHint(QPainter::Antialiasing, true); - int d = qMin(option->rect.width(), option->rect.height()); -/* if (d > 20 && option->notchTarget > 0) { - d += -1; - } -*/ QRectF r((option->rect.width() - d) / 2.0, (option->rect.height() - d) / 2.0, d, d); - const qreal angle = option->direction == Qt::LeftToRight ? 135.0 : 45.0; -// const qreal angle = 90; - - painter->setPen(Qt::NoPen); - QColor border_color = option->palette.color(QPalette::Window); -#if 0 - { - QRadialGradient depth_gradient(r.center(), d / 2); -// depth_gradient.setColorAt(0.0, QColor(0, 0, 0, 255)); - depth_gradient.setColorAt(0.5, QColor(0, 0, 0, 255)); - depth_gradient.setColorAt(1.0, QColor(0, 0, 0, 0)); - painter->setBrush(depth_gradient); - painter->drawEllipse(r); - } -#endif -#if 1 - if (option->state & QStyle::State_HasFocus && option->state & QStyle::State_KeyboardFocusChange) { - painter->setBrush(option->palette.color(QPalette::Highlight).darker(180)); - r.adjust(1, 1, -1, -1); - painter->drawEllipse(r); - painter->setBrush(border_color); - r.adjust(1, 1, -1, -1); - painter->drawEllipse(r); - r.adjust(1, 1, -1, -1); - } else { - painter->setBrush(border_color); - r.adjust(1, 1, -1, -1); - painter->drawEllipse(r); - r.adjust(1, 1, -1, -1); - QConicalGradient border_gradient(r.center(), angle); - if (!(option->state & QStyle::State_Enabled)) { - border_color = border_color.lighter(120); - } - border_gradient.setColorAt(0.0, border_color.darker(180)); - border_gradient.setColorAt(0.3, border_color.darker(130)); - border_gradient.setColorAt(0.5, border_color.darker(170)); - border_gradient.setColorAt(0.7, border_color.darker(130)); - border_gradient.setColorAt(1.0, border_color.darker(180)); - painter->setBrush(border_gradient); -// painter->setBrush(Qt::blue); - painter->drawEllipse(r); - r.adjust(1, 1, -1, -1); - } - d -= 6; - - QColor dial_color; - if (option->state & QStyle::State_Enabled) { - dial_color = option->palette.color(QPalette::Button).lighter(101); - if (option->state & QStyle::State_MouseOver) { - dial_color = dial_color.lighter(103); - } - } else { - dial_color = option->palette.color(QPalette::Window); - } - qreal t = option->state & QStyle::State_Enabled ? 2.0 : 1.5; - if (1) { - // ###: work around Qt 4.3.0 bug? (this works for 4.3.1) - QConicalGradient border_gradient(r.center(), angle); - border_gradient.setColorAt(0.0, dial_color.lighter(120)); - border_gradient.setColorAt(0.2, dial_color); - border_gradient.setColorAt(0.5, dial_color.darker(130)); - border_gradient.setColorAt(0.8, dial_color); - border_gradient.setColorAt(1.0, dial_color.lighter(120)); - painter->setPen(QPen(border_gradient, t)); - } else { - painter->setPen(QPen(Qt::red, t)); - } -#if 0 - QLinearGradient dial_gradient(r.topLeft(), r.bottomLeft()); - dial_gradient.setColorAt(0.0, dial_color.darker(105)); - dial_gradient.setColorAt(0.5, dial_color.lighter(102)); - dial_gradient.setColorAt(1.0, dial_color.lighter(105)); -#elif 1 - QLinearGradient dial_gradient(option->direction == Qt::LeftToRight ? r.topLeft() : r.topRight(), option->direction == Qt::LeftToRight ? r.bottomRight() : r.bottomLeft()); -// QLinearGradient dial_gradient(r.topLeft(), r.bottomLeft()); - if (true || option->state & QStyle::State_Enabled) { -#if 1 - dial_gradient.setColorAt(0.0, dial_color.darker(106)); - dial_gradient.setColorAt(1.0, dial_color.lighter(104)); -#else - dial_gradient.setColorAt(0.0, dial_color.lighter(101)); - dial_gradient.setColorAt(0.5, dial_color.darker(103)); - dial_gradient.setColorAt(1.0, dial_color.lighter(104)); -#endif - } else { - dial_gradient.setColorAt(0.0, dial_color); - dial_gradient.setColorAt(1.0, dial_color); - } -#elif 0 - QConicalGradient dial_gradient(r.center(), angle); - dial_gradient.setColorAt(0.0, dial_color.lighter(102)); - dial_gradient.setColorAt(0.5, dial_color.darker(103)); - dial_gradient.setColorAt(1.0, dial_color.lighter(102)); -#else - QBrush dial_gradient(dial_color); -#endif - painter->setBrush(dial_gradient); - t = t / 2; - painter->drawEllipse(r.adjusted(t, t, -t, -t)); - -// painter->setPen(Qt::NoPen); -// painter->setBrush(dial_color); -// painter->drawEllipse(r.adjusted(d / 4, d / 4, - d / 4, - d / 4)); - -#if 0 - QLinearGradient border2_gradient(r.topLeft(), r.bottomRight()); - border2_gradient.setColorAt(1.0, dial_color.darker(425)); - border2_gradient.setColorAt(0.9, dial_color); - border2_gradient.setColorAt(0.0, dial_color.darker(400)); - painter->setPen(QPen(border2_gradient, 1.3)); - painter->setBrush(Qt::NoBrush); - painter->drawEllipse(r.adjusted(0.3, 0.3, -0.3, -0.3)); -#endif -// painter->restore(); -#endif -} - -void -paintCachedDialBase(QPainter *painter, const QStyleOptionSlider *option) -{ - bool useCache = UsePixmapCache; - QString pixmapName; - QRect r = option->rect; - int d = qMin(r.width(), r.height()); - - if (/* option->state & (QStyle::State_HasFocus | QStyle::State_MouseOver) ||*/ d > 128) { - useCache = false; - } - if (useCache) { - uint state = uint(option->state) & (QStyle::State_Enabled | QStyle::State_On | QStyle::State_MouseOver | QStyle::State_KeyboardFocusChange | QStyle::State_HasFocus); - if (!(state & QStyle::State_Enabled)) { - state &= ~(QStyle::State_MouseOver | QStyle::State_HasFocus | QStyle::State_KeyboardFocusChange); - } - // state &= ~(QStyle::State_HasFocus); - pixmapName.sprintf("scp-qdb-%x-%x-%llx-%x", state, option->direction, option->palette.cacheKey(), d); - } - paintIndicatorCached(painter, option, paintDialBase, useCache, pixmapName); -} - -void -paintIndicatorDial(QPainter *painter, const QStyleOptionSlider *option) -{ - int d = qMin(option->rect.width(), option->rect.height()); - QRect rect(option->rect.center() - QPoint((d - 1) / 2, (d - 1) / 2), QSize(d, d)); - QStyleOptionSlider opt; - opt.QStyleOption::operator=(*option); - opt.rect = rect; - paintCachedDialBase(painter, &opt); -} - -QColor -shaded_color(const QColor &color, int shade) -{ -#if 1 - const qreal contrast = 1.0; - int r, g, b; - color.getRgb(&r, &g, &b); - int gray = qGray(r, g, b); - gray = qMax(r, qMax(g, b)); - gray = (r + b + g + 3 * gray) / 6; - if (shade < 0) { - qreal k = 220.0 / 255.0 * shade; - k *= contrast; - int a = 255; - if (gray > 0) { - a = int(k * 255 / (0 - gray)); - if (a < 0) a = 0; - if (a > 255) a = 255; - } - return QColor(0, 0, 0, a); - } else { - qreal k = (255 - 220.0) / (255.0) * shade; - k *= contrast; - int a = 255; - if (gray < 255) { - a = int(k * 255 / (255 - gray)); - if (a < 0) a = 0; - if (a > 255) a = 255; - } - return QColor(255, 255, 255, a); - } -#else - if (shade < 0) { - return QColor(0, 0, 0, -shade); - } else { - return QColor(255, 255, 255, shade); - } -#endif -} - -static void -paintGrip(QPainter *painter, const QStyleOption *option) -{ -// painter->fillRect(option->rect, Qt::red); - int d = qMin(option->rect.width(), option->rect.height()); - // good values are 3 (very small), 4 (small), 5 (good), 7 (large), 9 (huge) - // int d = 5; - QRectF rect(QRectF(option->rect).center() - QPointF(d / 2.0, d / 2.0), QSizeF(d, d)); - const qreal angle = option->direction == Qt::LeftToRight ? 135.0 : 45.0; -// const qreal angle = 90; - QColor color; - qreal opacity = 0.9; - - painter->save(); - painter->setPen(Qt::NoPen); - if (option->state & QStyle::State_Enabled) { - if (option->state & QStyle::State_Sunken) { - color = option->palette.color(QPalette::Highlight).darker(110); - } else { - color = option->palette.color(QPalette::Button); - } - } else { - color = option->palette.color(QPalette::Button); - opacity = 0.5; - } - - QConicalGradient gradient1(rect.center(), angle); - gradient1.setColorAt(0.0, shaded_color(color, -110)); - gradient1.setColorAt(0.25, shaded_color(color, -30)); - gradient1.setColorAt(0.5, shaded_color(color, 180)); - gradient1.setColorAt(0.75, shaded_color(color, -30)); - gradient1.setColorAt(1.0, shaded_color(color, -110)); - painter->setBrush(color); - painter->drawEllipse(rect); - painter->setBrush(gradient1); -#if (QT_VERSION >= QT_VERSION_CHECK(4, 2, 0)) - // ### merge opacity into color - painter->setOpacity(opacity); -#endif - painter->drawEllipse(rect); -#if (QT_VERSION >= QT_VERSION_CHECK(4, 2, 0)) - painter->setOpacity(1.0); - if (d > 2) { - QConicalGradient gradient2(rect.center(), angle); - gradient2.setColorAt(0.0, shaded_color(color, -40)); - gradient2.setColorAt(0.25, shaded_color(color, 0)); - gradient2.setColorAt(0.5, shaded_color(color, 210)); - gradient2.setColorAt(0.75, shaded_color(color, 0)); - gradient2.setColorAt(1.0, shaded_color(color, -40)); - rect.adjust(1, 1, -1, -1); - painter->setBrush(color); - painter->drawEllipse(rect); - painter->setBrush(gradient2); - painter->setOpacity(opacity); - painter->drawEllipse(rect); - painter->setOpacity(1.0); - if (d > 8) { - QConicalGradient gradient3(rect.center(), angle); - gradient3.setColorAt(0.0, shaded_color(color, -10)); - gradient3.setColorAt(0.25, shaded_color(color, 0)); - gradient3.setColorAt(0.5, shaded_color(color, 180)); - gradient3.setColorAt(0.75, shaded_color(color, 0)); - gradient3.setColorAt(1.0, shaded_color(color, -10)); - rect.adjust(2, 2, -2, -2); - painter->setBrush(color); - painter->drawEllipse(rect); - painter->setBrush(gradient3); - painter->setOpacity(opacity); - painter->drawEllipse(rect); - painter->setOpacity(1.0); - } - } -#endif - painter->restore(); -} - -void -paintCachedGrip(QPainter *painter, const QStyleOption *option, QPalette::ColorRole /*bgrole*/) -{ - bool useCache = UsePixmapCache; - QString pixmapName; - - if (/* option->state & (QStyle::State_HasFocus | QStyle::State_MouseOver) ||*/ option->rect.width() * option->rect.height() > 4096) { - useCache = false; - } - if (useCache) { - uint state = uint(option->state) & (QStyle::State_Enabled | QStyle::State_On | QStyle::State_MouseOver | QStyle::State_Sunken | QStyle::State_HasFocus); - if (!(state & QStyle::State_Enabled)) { - state &= ~(QStyle::State_MouseOver | QStyle::State_HasFocus); - } - state &= ~(QStyle::State_HasFocus); - QByteArray colorName = option->palette.color(QPalette::Button).name().toLatin1(); - pixmapName.sprintf("scp-isg-%x-%x-%s-%x-%x", state, option->direction, colorName.constData(), option->rect.width(), option->rect.height()); - } - paintIndicatorCached(painter, option, paintGrip, useCache, pixmapName); -} - -void -QDialSkulptureStyle::drawComplexControl( ComplexControl cc, - const QStyleOptionComplex *optc, - QPainter *painter, - const QWidget *widget) const -{ - - if (cc != QStyle::CC_Dial) { - QCommonStyle::drawComplexControl(cc, optc, painter, widget); - return; - } - - const QStyleOptionSlider *option = qstyleoption_cast(optc); - if (option == NULL) - return; - - int d = qMin(option->rect.width() & ~1, option->rect.height() & ~1); - QStyleOptionSlider opt = *option; - const QAbstractSlider *slider = NULL; - // always highlight knob if pressed (even if mouse is not over knob) - if ((option->state & QStyle::State_HasFocus) && (slider = qobject_cast(widget))) { - if (slider->isSliderDown()) { - opt.state |= QStyle::State_MouseOver; - } - } - - // tickmarks - opt.palette.setColor(QPalette::Inactive, QPalette::WindowText, QColor(80, 80, 80, 255)); - opt.palette.setColor(QPalette::Active, QPalette::WindowText, QColor(80, 80, 80, 255)); - opt.state &= ~QStyle::State_HasFocus; - opt.rect.setWidth(opt.rect.width() & ~1); - opt.rect.setHeight(opt.rect.height() & ~1); - //((QCommonStyle *) this)-> - QCommonStyle::drawComplexControl(QStyle::CC_Dial, &opt, painter, widget); - - // focus rectangle - if (option->state & QStyle::State_HasFocus) { - QStyleOptionFocusRect focus; - opt.state |= QStyle::State_HasFocus; - focus.QStyleOption::operator=(opt); - focus.rect.adjust(-1, -1, 1, 1); - //drawPrimitive(QStyle::PE_FrameFocusRect, &focus, painter, widget); - } - opt.palette = option->palette; - - // dial base - if (d <= 256) { - paintIndicatorDial(painter, &opt); - } else { - // large dials are slow to render, do not render them - } - - // dial knob - d -= 6; - int gripSize = (option->fontMetrics.height() / 4) * 2 - 1; - opt.rect.setSize(QSize(gripSize, gripSize)); - opt.rect.moveCenter(option->rect.center()); - // angle calculation from qcommonstyle.cpp (c) Trolltech 1992-2007, ASA. - qreal angle; - int sliderPosition = option->upsideDown ? option->sliderPosition : (option->maximum - option->sliderPosition); - int range = option->maximum - option->minimum; - if (!range) { - angle = M_PI / 2; - } else if (option->dialWrapping) { - angle = M_PI * 1.5 - (sliderPosition - option->minimum) * 2 * M_PI / range; - } else { - angle = (M_PI * 8 - (sliderPosition - option->minimum) * 10 * M_PI / range) / 6; - } - - qreal rr = d / 2.0 - gripSize - 2; - opt.rect.translate(int(0.5 + rr * cos(angle)), int(0.5 - rr * sin(angle))); - paintCachedGrip(painter, &opt, option->state & QStyle::State_Enabled ? QPalette::Button : QPalette::Window); -} diff --git a/qdialskulpturestyle.hpp b/qdialskulpturestyle.hpp deleted file mode 100644 index 2f3ba04..0000000 --- a/qdialskulpturestyle.hpp +++ /dev/null @@ -1,39 +0,0 @@ -/****************************************************************************** - - Skulpture - Classical Three-Dimensional Artwork for Qt 4 - - Copyright (c) 2007-2009 Christoph Feck - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -*****************************************************************************/ - -#ifndef QDIALSKULPTURESTYLE_H -#define QDIALSKULPTURESTYLE_H - -#include - -class QDialSkulptureStyle:public QCommonStyle -{ -public: - QDialSkulptureStyle(){} - virtual ~QDialSkulptureStyle(){} - - virtual void drawComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, QPainter *p, - const QWidget *widget=0) const; - -}; - -#endif // QDIALSKULPTURESTYLE_H diff --git a/qmidiplayer.pro b/qmidiplayer.pro index da193e2..63e20b6 100644 --- a/qmidiplayer.pro +++ b/qmidiplayer.pro @@ -12,42 +12,42 @@ TARGET = qmidiplayer TEMPLATE = app -SOURCES += main.cpp\ - qmpmainwindow.cpp \ - qmpmidiplay.cpp \ - qmpmidiread.cpp \ - qmpplistwindow.cpp \ - qmpchannelswindow.cpp \ - qmppresetselect.cpp \ - qmpchanneleditor.cpp \ - qmpefxwindow.cpp \ - qmpinfowindow.cpp \ - qmpsettingswindow.cpp \ - qmphelpwindow.cpp \ - qdialskulpturestyle.cpp +SOURCES += ./qmidiplayer.src.d/main.cpp\ + ./qmidiplayer.src.d/qmpmainwindow.cpp \ + ./common/qmpmidiplay.cpp \ + ./common/qmpmidiread.cpp \ + ./qmidiplayer.src.d/qmpplistwindow.cpp \ + ./qmidiplayer.src.d/qmpchannelswindow.cpp \ + ./qmidiplayer.src.d/qmppresetselect.cpp \ + ./qmidiplayer.src.d/qmpchanneleditor.cpp \ + ./qmidiplayer.src.d/qmpefxwindow.cpp \ + ./qmidiplayer.src.d/qmpinfowindow.cpp \ + ./qmidiplayer.src.d/qmpsettingswindow.cpp \ + ./qmidiplayer.src.d/qmphelpwindow.cpp \ + ./qmidiplayer.src.d/qdialskulpturestyle.cpp -HEADERS += qmpmainwindow.hpp \ - qmpmidiplay.hpp \ - qmpplistwindow.hpp \ - qmpchannelswindow.hpp \ - qmppresetselect.hpp \ - qmpchanneleditor.hpp \ - qmpefxwindow.hpp \ - qmpinfowindow.hpp \ - qmpsettingswindow.hpp \ - qmphelpwindow.hpp \ - qdialskulpturestyle.hpp \ - qmpimidimapper.hpp +HEADERS += ./qmidiplayer.src.d/qmpmainwindow.hpp \ + ./common/qmpmidiplay.hpp \ + ./qmidiplayer.src.d/qmpplistwindow.hpp \ + ./qmidiplayer.src.d/qmpchannelswindow.hpp \ + ./qmidiplayer.src.d/qmppresetselect.hpp \ + ./qmidiplayer.src.d/qmpchanneleditor.hpp \ + ./qmidiplayer.src.d/qmpefxwindow.hpp \ + ./qmidiplayer.src.d/qmpinfowindow.hpp \ + ./qmidiplayer.src.d/qmpsettingswindow.hpp \ + ./qmidiplayer.src.d/qmphelpwindow.hpp \ + ./qmidiplayer.src.d/qdialskulpturestyle.hpp \ + ./qmidiplayer.src.d/qmpimidimapper.hpp -FORMS += qmpmainwindow.ui \ - qmpplistwindow.ui \ - qmpchannelswindow.ui \ - qmppresetselect.ui \ - qmpchanneleditor.ui \ - qmpefxwindow.ui \ - qmpinfowindow.ui \ - qmpsettingswindow.ui \ - qmphelpwindow.ui +FORMS += ./qmidiplayer.src.d/qmpmainwindow.ui \ + ./qmidiplayer.src.d/qmpplistwindow.ui \ + ./qmidiplayer.src.d/qmpchannelswindow.ui \ + ./qmidiplayer.src.d/qmppresetselect.ui \ + ./qmidiplayer.src.d/qmpchanneleditor.ui \ + ./qmidiplayer.src.d/qmpefxwindow.ui \ + ./qmidiplayer.src.d/qmpinfowindow.ui \ + ./qmidiplayer.src.d/qmpsettingswindow.ui \ + ./qmidiplayer.src.d/qmphelpwindow.ui unix{ isEmpty(PREFIX) { @@ -59,6 +59,6 @@ unix{ QMAKE_CXXFLAGS += -std=c++11 -Wall LIBS += -lfluidsynth } -win32:LIBS += e:/libs/fluidsynth/fluidsynth.lib #You have to change these -win32:INCLUDEPATH += e:/libs/fluidsynth/include #before building... -RESOURCES = resources.qrc +win32:LIBS += e:/libs/fluidsynth/fluidsynth.lib winmm.lib #You have to change these +win32:INCLUDEPATH += e:/libs/fluidsynth/include #before building... +RESOURCES = ./qmidiplayer.src.d/resources.qrc diff --git a/qmidiplayer.src.d/main.cpp b/qmidiplayer.src.d/main.cpp new file mode 100644 index 0000000..c9f3b42 --- /dev/null +++ b/qmidiplayer.src.d/main.cpp @@ -0,0 +1,29 @@ +/* + *QMidiPlayer, a cross-platform player for midi files. + *Copyright (C) 2015 Chris Xiong + * + *This program is free software: you can redistribute it and/or modify + *it under the terms of the GNU General Public License as published by + *the Free Software Foundation, either version 3 of the License, or + *(at your option) any later version. + * + *This program is distributed in the hope that it will be useful, + *but WITHOUT ANY WARRANTY; without even the implied warranty of + *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + *GNU General Public License for more details. + * + *You should have received a copy of the GNU General Public License + *along with this program. If not, see . + */ +#include "qmpmainwindow.hpp" +#include +#include + +int main(int argc,char **argv) +{ + QApplication a(argc,argv); + qmpMainWindow w; + if(w.pharseArgs(argc,argv)==1)return 0; + + return a.exec(); +} diff --git a/qmidiplayer.src.d/qdialskulpturestyle.cpp b/qmidiplayer.src.d/qdialskulpturestyle.cpp new file mode 100644 index 0000000..7c181a0 --- /dev/null +++ b/qmidiplayer.src.d/qdialskulpturestyle.cpp @@ -0,0 +1,437 @@ +/****************************************************************************** + + Skulpture - Classical Three-Dimensional Artwork for Qt 4 + + Copyright (c) 2007-2009 Christoph Feck + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +*****************************************************************************/ +#include +#include +#include +#include + +#include "qdialskulpturestyle.hpp" + +#ifndef M_PI +#define M_PI 3.141592653589793f +#endif + +static const bool UsePixmapCache = true; + +static void +paintIndicatorCached(QPainter *painter, const QStyleOption *option, void (*paintIndicator)(QPainter *painter, const QStyleOption *option), bool useCache, const QString &pixmapName) +{ + QPixmap pixmap; + + if (!useCache || !QPixmapCache::find(pixmapName, pixmap)) { + pixmap = QPixmap(option->rect.size()); +#if 1 + pixmap.fill(Qt::transparent); + // pixmap.fill(Qt::red); +#else + pixmap.fill(option->palette.color(QPalette::Window)); +#endif + QPainter p(&pixmap); + QStyleOption opt = *option; + opt.rect = QRect(QPoint(0, 0), option->rect.size()); + // p.setCompositionMode(QPainter::CompositionMode_Clear); + // p.setCompositionMode(QPainter::CompositionMode_Source); + // p.fillRect(opt.rect, Qt::transparent); + // p.setCompositionMode(QPainter::CompositionMode_SourceOver); + p.setFont(painter->font()); + p.setRenderHint(QPainter::Antialiasing, true); + paintIndicator(&p, &opt); + p.end(); + if (useCache) { + QPixmapCache::insert(pixmapName, pixmap); + // qDebug() << "inserted into cache:" << pixmapName; + } + } + painter->drawPixmap(option->rect, pixmap); +} + +void +paintDialBase(QPainter *painter, const QStyleOption *option) +{ +// painter->fillRect(option->rect, Qt::red); +// painter->save(); +// painter->setRenderHint(QPainter::Antialiasing, true); + int d = qMin(option->rect.width(), option->rect.height()); +/* if (d > 20 && option->notchTarget > 0) { + d += -1; + } +*/ QRectF r((option->rect.width() - d) / 2.0, (option->rect.height() - d) / 2.0, d, d); + const qreal angle = option->direction == Qt::LeftToRight ? 135.0 : 45.0; +// const qreal angle = 90; + + painter->setPen(Qt::NoPen); + QColor border_color = option->palette.color(QPalette::Window); +#if 0 + { + QRadialGradient depth_gradient(r.center(), d / 2); +// depth_gradient.setColorAt(0.0, QColor(0, 0, 0, 255)); + depth_gradient.setColorAt(0.5, QColor(0, 0, 0, 255)); + depth_gradient.setColorAt(1.0, QColor(0, 0, 0, 0)); + painter->setBrush(depth_gradient); + painter->drawEllipse(r); + } +#endif +#if 1 + if (option->state & QStyle::State_HasFocus && option->state & QStyle::State_KeyboardFocusChange) { + painter->setBrush(option->palette.color(QPalette::Highlight).darker(180)); + r.adjust(1, 1, -1, -1); + painter->drawEllipse(r); + painter->setBrush(border_color); + r.adjust(1, 1, -1, -1); + painter->drawEllipse(r); + r.adjust(1, 1, -1, -1); + } else { + painter->setBrush(border_color); + r.adjust(1, 1, -1, -1); + painter->drawEllipse(r); + r.adjust(1, 1, -1, -1); + QConicalGradient border_gradient(r.center(), angle); + if (!(option->state & QStyle::State_Enabled)) { + border_color = border_color.lighter(120); + } + border_gradient.setColorAt(0.0, border_color.darker(180)); + border_gradient.setColorAt(0.3, border_color.darker(130)); + border_gradient.setColorAt(0.5, border_color.darker(170)); + border_gradient.setColorAt(0.7, border_color.darker(130)); + border_gradient.setColorAt(1.0, border_color.darker(180)); + painter->setBrush(border_gradient); +// painter->setBrush(Qt::blue); + painter->drawEllipse(r); + r.adjust(1, 1, -1, -1); + } + d -= 6; + + QColor dial_color; + if (option->state & QStyle::State_Enabled) { + dial_color = option->palette.color(QPalette::Button).lighter(101); + if (option->state & QStyle::State_MouseOver) { + dial_color = dial_color.lighter(103); + } + } else { + dial_color = option->palette.color(QPalette::Window); + } + qreal t = option->state & QStyle::State_Enabled ? 2.0 : 1.5; + if (1) { + // ###: work around Qt 4.3.0 bug? (this works for 4.3.1) + QConicalGradient border_gradient(r.center(), angle); + border_gradient.setColorAt(0.0, dial_color.lighter(120)); + border_gradient.setColorAt(0.2, dial_color); + border_gradient.setColorAt(0.5, dial_color.darker(130)); + border_gradient.setColorAt(0.8, dial_color); + border_gradient.setColorAt(1.0, dial_color.lighter(120)); + painter->setPen(QPen(border_gradient, t)); + } else { + painter->setPen(QPen(Qt::red, t)); + } +#if 0 + QLinearGradient dial_gradient(r.topLeft(), r.bottomLeft()); + dial_gradient.setColorAt(0.0, dial_color.darker(105)); + dial_gradient.setColorAt(0.5, dial_color.lighter(102)); + dial_gradient.setColorAt(1.0, dial_color.lighter(105)); +#elif 1 + QLinearGradient dial_gradient(option->direction == Qt::LeftToRight ? r.topLeft() : r.topRight(), option->direction == Qt::LeftToRight ? r.bottomRight() : r.bottomLeft()); +// QLinearGradient dial_gradient(r.topLeft(), r.bottomLeft()); + if (true || option->state & QStyle::State_Enabled) { +#if 1 + dial_gradient.setColorAt(0.0, dial_color.darker(106)); + dial_gradient.setColorAt(1.0, dial_color.lighter(104)); +#else + dial_gradient.setColorAt(0.0, dial_color.lighter(101)); + dial_gradient.setColorAt(0.5, dial_color.darker(103)); + dial_gradient.setColorAt(1.0, dial_color.lighter(104)); +#endif + } else { + dial_gradient.setColorAt(0.0, dial_color); + dial_gradient.setColorAt(1.0, dial_color); + } +#elif 0 + QConicalGradient dial_gradient(r.center(), angle); + dial_gradient.setColorAt(0.0, dial_color.lighter(102)); + dial_gradient.setColorAt(0.5, dial_color.darker(103)); + dial_gradient.setColorAt(1.0, dial_color.lighter(102)); +#else + QBrush dial_gradient(dial_color); +#endif + painter->setBrush(dial_gradient); + t = t / 2; + painter->drawEllipse(r.adjusted(t, t, -t, -t)); + +// painter->setPen(Qt::NoPen); +// painter->setBrush(dial_color); +// painter->drawEllipse(r.adjusted(d / 4, d / 4, - d / 4, - d / 4)); + +#if 0 + QLinearGradient border2_gradient(r.topLeft(), r.bottomRight()); + border2_gradient.setColorAt(1.0, dial_color.darker(425)); + border2_gradient.setColorAt(0.9, dial_color); + border2_gradient.setColorAt(0.0, dial_color.darker(400)); + painter->setPen(QPen(border2_gradient, 1.3)); + painter->setBrush(Qt::NoBrush); + painter->drawEllipse(r.adjusted(0.3, 0.3, -0.3, -0.3)); +#endif +// painter->restore(); +#endif +} + +void +paintCachedDialBase(QPainter *painter, const QStyleOptionSlider *option) +{ + bool useCache = UsePixmapCache; + QString pixmapName; + QRect r = option->rect; + int d = qMin(r.width(), r.height()); + + if (/* option->state & (QStyle::State_HasFocus | QStyle::State_MouseOver) ||*/ d > 128) { + useCache = false; + } + if (useCache) { + uint state = uint(option->state) & (QStyle::State_Enabled | QStyle::State_On | QStyle::State_MouseOver | QStyle::State_KeyboardFocusChange | QStyle::State_HasFocus); + if (!(state & QStyle::State_Enabled)) { + state &= ~(QStyle::State_MouseOver | QStyle::State_HasFocus | QStyle::State_KeyboardFocusChange); + } + // state &= ~(QStyle::State_HasFocus); + pixmapName.sprintf("scp-qdb-%x-%x-%llx-%x", state, option->direction, option->palette.cacheKey(), d); + } + paintIndicatorCached(painter, option, paintDialBase, useCache, pixmapName); +} + +void +paintIndicatorDial(QPainter *painter, const QStyleOptionSlider *option) +{ + int d = qMin(option->rect.width(), option->rect.height()); + QRect rect(option->rect.center() - QPoint((d - 1) / 2, (d - 1) / 2), QSize(d, d)); + QStyleOptionSlider opt; + opt.QStyleOption::operator=(*option); + opt.rect = rect; + paintCachedDialBase(painter, &opt); +} + +QColor +shaded_color(const QColor &color, int shade) +{ +#if 1 + const qreal contrast = 1.0; + int r, g, b; + color.getRgb(&r, &g, &b); + int gray = qGray(r, g, b); + gray = qMax(r, qMax(g, b)); + gray = (r + b + g + 3 * gray) / 6; + if (shade < 0) { + qreal k = 220.0 / 255.0 * shade; + k *= contrast; + int a = 255; + if (gray > 0) { + a = int(k * 255 / (0 - gray)); + if (a < 0) a = 0; + if (a > 255) a = 255; + } + return QColor(0, 0, 0, a); + } else { + qreal k = (255 - 220.0) / (255.0) * shade; + k *= contrast; + int a = 255; + if (gray < 255) { + a = int(k * 255 / (255 - gray)); + if (a < 0) a = 0; + if (a > 255) a = 255; + } + return QColor(255, 255, 255, a); + } +#else + if (shade < 0) { + return QColor(0, 0, 0, -shade); + } else { + return QColor(255, 255, 255, shade); + } +#endif +} + +static void +paintGrip(QPainter *painter, const QStyleOption *option) +{ +// painter->fillRect(option->rect, Qt::red); + int d = qMin(option->rect.width(), option->rect.height()); + // good values are 3 (very small), 4 (small), 5 (good), 7 (large), 9 (huge) + // int d = 5; + QRectF rect(QRectF(option->rect).center() - QPointF(d / 2.0, d / 2.0), QSizeF(d, d)); + const qreal angle = option->direction == Qt::LeftToRight ? 135.0 : 45.0; +// const qreal angle = 90; + QColor color; + qreal opacity = 0.9; + + painter->save(); + painter->setPen(Qt::NoPen); + if (option->state & QStyle::State_Enabled) { + if (option->state & QStyle::State_Sunken) { + color = option->palette.color(QPalette::Highlight).darker(110); + } else { + color = option->palette.color(QPalette::Button); + } + } else { + color = option->palette.color(QPalette::Button); + opacity = 0.5; + } + + QConicalGradient gradient1(rect.center(), angle); + gradient1.setColorAt(0.0, shaded_color(color, -110)); + gradient1.setColorAt(0.25, shaded_color(color, -30)); + gradient1.setColorAt(0.5, shaded_color(color, 180)); + gradient1.setColorAt(0.75, shaded_color(color, -30)); + gradient1.setColorAt(1.0, shaded_color(color, -110)); + painter->setBrush(color); + painter->drawEllipse(rect); + painter->setBrush(gradient1); +#if (QT_VERSION >= QT_VERSION_CHECK(4, 2, 0)) + // ### merge opacity into color + painter->setOpacity(opacity); +#endif + painter->drawEllipse(rect); +#if (QT_VERSION >= QT_VERSION_CHECK(4, 2, 0)) + painter->setOpacity(1.0); + if (d > 2) { + QConicalGradient gradient2(rect.center(), angle); + gradient2.setColorAt(0.0, shaded_color(color, -40)); + gradient2.setColorAt(0.25, shaded_color(color, 0)); + gradient2.setColorAt(0.5, shaded_color(color, 210)); + gradient2.setColorAt(0.75, shaded_color(color, 0)); + gradient2.setColorAt(1.0, shaded_color(color, -40)); + rect.adjust(1, 1, -1, -1); + painter->setBrush(color); + painter->drawEllipse(rect); + painter->setBrush(gradient2); + painter->setOpacity(opacity); + painter->drawEllipse(rect); + painter->setOpacity(1.0); + if (d > 8) { + QConicalGradient gradient3(rect.center(), angle); + gradient3.setColorAt(0.0, shaded_color(color, -10)); + gradient3.setColorAt(0.25, shaded_color(color, 0)); + gradient3.setColorAt(0.5, shaded_color(color, 180)); + gradient3.setColorAt(0.75, shaded_color(color, 0)); + gradient3.setColorAt(1.0, shaded_color(color, -10)); + rect.adjust(2, 2, -2, -2); + painter->setBrush(color); + painter->drawEllipse(rect); + painter->setBrush(gradient3); + painter->setOpacity(opacity); + painter->drawEllipse(rect); + painter->setOpacity(1.0); + } + } +#endif + painter->restore(); +} + +void +paintCachedGrip(QPainter *painter, const QStyleOption *option, QPalette::ColorRole /*bgrole*/) +{ + bool useCache = UsePixmapCache; + QString pixmapName; + + if (/* option->state & (QStyle::State_HasFocus | QStyle::State_MouseOver) ||*/ option->rect.width() * option->rect.height() > 4096) { + useCache = false; + } + if (useCache) { + uint state = uint(option->state) & (QStyle::State_Enabled | QStyle::State_On | QStyle::State_MouseOver | QStyle::State_Sunken | QStyle::State_HasFocus); + if (!(state & QStyle::State_Enabled)) { + state &= ~(QStyle::State_MouseOver | QStyle::State_HasFocus); + } + state &= ~(QStyle::State_HasFocus); + QByteArray colorName = option->palette.color(QPalette::Button).name().toLatin1(); + pixmapName.sprintf("scp-isg-%x-%x-%s-%x-%x", state, option->direction, colorName.constData(), option->rect.width(), option->rect.height()); + } + paintIndicatorCached(painter, option, paintGrip, useCache, pixmapName); +} + +void +QDialSkulptureStyle::drawComplexControl( ComplexControl cc, + const QStyleOptionComplex *optc, + QPainter *painter, + const QWidget *widget) const +{ + + if (cc != QStyle::CC_Dial) { + QCommonStyle::drawComplexControl(cc, optc, painter, widget); + return; + } + + const QStyleOptionSlider *option = qstyleoption_cast(optc); + if (option == NULL) + return; + + int d = qMin(option->rect.width() & ~1, option->rect.height() & ~1); + QStyleOptionSlider opt = *option; + const QAbstractSlider *slider = NULL; + // always highlight knob if pressed (even if mouse is not over knob) + if ((option->state & QStyle::State_HasFocus) && (slider = qobject_cast(widget))) { + if (slider->isSliderDown()) { + opt.state |= QStyle::State_MouseOver; + } + } + + // tickmarks + opt.palette.setColor(QPalette::Inactive, QPalette::WindowText, QColor(80, 80, 80, 255)); + opt.palette.setColor(QPalette::Active, QPalette::WindowText, QColor(80, 80, 80, 255)); + opt.state &= ~QStyle::State_HasFocus; + opt.rect.setWidth(opt.rect.width() & ~1); + opt.rect.setHeight(opt.rect.height() & ~1); + //((QCommonStyle *) this)-> + QCommonStyle::drawComplexControl(QStyle::CC_Dial, &opt, painter, widget); + + // focus rectangle + if (option->state & QStyle::State_HasFocus) { + QStyleOptionFocusRect focus; + opt.state |= QStyle::State_HasFocus; + focus.QStyleOption::operator=(opt); + focus.rect.adjust(-1, -1, 1, 1); + //drawPrimitive(QStyle::PE_FrameFocusRect, &focus, painter, widget); + } + opt.palette = option->palette; + + // dial base + if (d <= 256) { + paintIndicatorDial(painter, &opt); + } else { + // large dials are slow to render, do not render them + } + + // dial knob + d -= 6; + int gripSize = (option->fontMetrics.height() / 4) * 2 - 1; + opt.rect.setSize(QSize(gripSize, gripSize)); + opt.rect.moveCenter(option->rect.center()); + // angle calculation from qcommonstyle.cpp (c) Trolltech 1992-2007, ASA. + qreal angle; + int sliderPosition = option->upsideDown ? option->sliderPosition : (option->maximum - option->sliderPosition); + int range = option->maximum - option->minimum; + if (!range) { + angle = M_PI / 2; + } else if (option->dialWrapping) { + angle = M_PI * 1.5 - (sliderPosition - option->minimum) * 2 * M_PI / range; + } else { + angle = (M_PI * 8 - (sliderPosition - option->minimum) * 10 * M_PI / range) / 6; + } + + qreal rr = d / 2.0 - gripSize - 2; + opt.rect.translate(int(0.5 + rr * cos(angle)), int(0.5 - rr * sin(angle))); + paintCachedGrip(painter, &opt, option->state & QStyle::State_Enabled ? QPalette::Button : QPalette::Window); +} diff --git a/qmidiplayer.src.d/qdialskulpturestyle.hpp b/qmidiplayer.src.d/qdialskulpturestyle.hpp new file mode 100644 index 0000000..2f3ba04 --- /dev/null +++ b/qmidiplayer.src.d/qdialskulpturestyle.hpp @@ -0,0 +1,39 @@ +/****************************************************************************** + + Skulpture - Classical Three-Dimensional Artwork for Qt 4 + + Copyright (c) 2007-2009 Christoph Feck + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +*****************************************************************************/ + +#ifndef QDIALSKULPTURESTYLE_H +#define QDIALSKULPTURESTYLE_H + +#include + +class QDialSkulptureStyle:public QCommonStyle +{ +public: + QDialSkulptureStyle(){} + virtual ~QDialSkulptureStyle(){} + + virtual void drawComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, QPainter *p, + const QWidget *widget=0) const; + +}; + +#endif // QDIALSKULPTURESTYLE_H diff --git a/qmidiplayer.src.d/qmpchanneleditor.cpp b/qmidiplayer.src.d/qmpchanneleditor.cpp new file mode 100644 index 0000000..f1d4e5e --- /dev/null +++ b/qmidiplayer.src.d/qmpchanneleditor.cpp @@ -0,0 +1,193 @@ +#include +#include "qmpchanneleditor.hpp" +#include "ui_qmpchanneleditor.h" +#include "qmpmainwindow.hpp" + +qmpChannelEditor::qmpChannelEditor(QWidget *parent) : + QDialog(parent), + ui(new Ui::qmpChannelEditor) +{ + ui->setupUi(this); + styl=new QDialSkulptureStyle(); + QList dials=findChildren(); + for(int i=0;isetStyle(styl); +} + +qmpChannelEditor::~qmpChannelEditor() +{ + delete styl; + delete ui; +} + +void qmpChannelEditor::setupWindow(int chid) +{ + char str[256];if(~chid)ch=chid; + sprintf(str,"Channel Parameter Editor - Channel #%d",ch+1); + setWindowTitle(str); + CMidiPlayer* player=qmpMainWindow::getInstance()->getPlayer(); + int b,p; + player->getChannelPreset(ch,&b,&p,str); + ui->lbPresetName->setText(str); + sprintf(str,"BK: %d",b);ui->lbBank->setText(str); + sprintf(str,"PC: %d",p);ui->lbPreset->setText(str); + ui->lbChannelNumber->setText(QString::number(ch+1)); +#define setupControl(ccid,lb,d,ccname)\ + b=player->getCC(ch,ccid);\ + sprintf(str,"%s %d",ccname,b);\ + ui->lb->setText(str);\ + ui->d->setValue(b); + setupControl(7,lbVol,dVol,"Vol."); + setupControl(91,lbReverb,dReverb,"Rev."); + setupControl(93,lbChorus,dChorus,"Chr."); + setupControl(71,lbReso,dReso,"Res."); + setupControl(74,lbCut,dCut,"Cut."); + setupControl(73,lbAttack,dAttack,"Atk."); + setupControl(75,lbDecay,dDecay,"Dec."); + setupControl(72,lbRelease,dRelease,"Rel."); + setupControl(76,lbRate,dRate,"Rate"); + setupControl(77,lbDepth,dDepth,"Dep."); + setupControl(78,lbDelay,dDelay,"Del."); + b=player->getCC(ch,10); + if(b==64)strcpy(str,"Pan. C"); + else if(b<64)sprintf(str,"Pan. L%d",64-b);else sprintf(str,"Pan. R%d",b-64); + ui->lbPan->setText(str); + ui->dPan->setValue(b); +} + +void qmpChannelEditor::sendCC() +{ + CMidiPlayer* player=qmpMainWindow::getInstance()->getPlayer(); + player->setCC(ch,7,ui->dVol->value()); + player->setCC(ch,10,ui->dPan->value()); + player->setCC(ch,91,ui->dReverb->value()); + player->setCC(ch,93,ui->dChorus->value()); + player->setCC(ch,71,ui->dReso->value()); + player->setCC(ch,74,ui->dCut->value()); + player->setCC(ch,73,ui->dAttack->value()); + player->setCC(ch,75,ui->dDecay->value()); + player->setCC(ch,72,ui->dRelease->value()); + player->setCC(ch,76,ui->dRate->value()); + player->setCC(ch,77,ui->dDepth->value()); + player->setCC(ch,78,ui->dDelay->value()); +} + +void qmpChannelEditor::showEvent(QShowEvent *e) +{ + knobpressed=0; + setupWindow(); + connectSlots(); + connect(qmpMainWindow::getInstance()->getTimer(),SIGNAL(timeout()),this,SLOT(setupWindow())); + e->accept(); +} +void qmpChannelEditor::closeEvent(QCloseEvent *e) +{ + disconnectSlots(); + disconnect(qmpMainWindow::getInstance()->getTimer(),SIGNAL(timeout()),this,SLOT(setupWindow())); + e->accept(); +} + +void qmpChannelEditor::on_pbChLeft_clicked() +{ + disconnectSlots(); + if(ch>0)--ch;else ch=15;setupWindow(); + connectSlots(); +} + +void qmpChannelEditor::on_pbChRight_clicked() +{ + disconnectSlots(); + if(ch<15)++ch;else ch=0;setupWindow(); + connectSlots(); +} + +void qmpChannelEditor::commonPressed() +{disconnect(qmpMainWindow::getInstance()->getTimer(),SIGNAL(timeout()),this,SLOT(setupWindow()));knobpressed=1;} +void qmpChannelEditor::commonReleased() +{connect(qmpMainWindow::getInstance()->getTimer(),SIGNAL(timeout()),this,SLOT(setupWindow()));sendCC();knobpressed=0;} +void qmpChannelEditor::commonChanged() +{if(knobpressed){sendCC();setupWindow();}} + +void qmpChannelEditor::connectSlots() +{ + connect(ui->dCut,SIGNAL(sliderPressed()),this,SLOT(commonPressed())); + connect(ui->dReso,SIGNAL(sliderPressed()),this,SLOT(commonPressed())); + connect(ui->dReverb,SIGNAL(sliderPressed()),this,SLOT(commonPressed())); + connect(ui->dChorus,SIGNAL(sliderPressed()),this,SLOT(commonPressed())); + connect(ui->dVol,SIGNAL(sliderPressed()),this,SLOT(commonPressed())); + connect(ui->dPan,SIGNAL(sliderPressed()),this,SLOT(commonPressed())); + connect(ui->dAttack,SIGNAL(sliderPressed()),this,SLOT(commonPressed())); + connect(ui->dDecay,SIGNAL(sliderPressed()),this,SLOT(commonPressed())); + connect(ui->dRelease,SIGNAL(sliderPressed()),this,SLOT(commonPressed())); + connect(ui->dRate,SIGNAL(sliderPressed()),this,SLOT(commonPressed())); + connect(ui->dDepth,SIGNAL(sliderPressed()),this,SLOT(commonPressed())); + connect(ui->dDelay,SIGNAL(sliderPressed()),this,SLOT(commonPressed())); + + connect(ui->dCut,SIGNAL(sliderReleased()),this,SLOT(commonReleased())); + connect(ui->dReso,SIGNAL(sliderReleased()),this,SLOT(commonReleased())); + connect(ui->dReverb,SIGNAL(sliderReleased()),this,SLOT(commonReleased())); + connect(ui->dChorus,SIGNAL(sliderReleased()),this,SLOT(commonReleased())); + connect(ui->dVol,SIGNAL(sliderReleased()),this,SLOT(commonReleased())); + connect(ui->dPan,SIGNAL(sliderReleased()),this,SLOT(commonReleased())); + connect(ui->dAttack,SIGNAL(sliderReleased()),this,SLOT(commonReleased())); + connect(ui->dDecay,SIGNAL(sliderReleased()),this,SLOT(commonReleased())); + connect(ui->dRelease,SIGNAL(sliderReleased()),this,SLOT(commonReleased())); + connect(ui->dRate,SIGNAL(sliderReleased()),this,SLOT(commonReleased())); + connect(ui->dDepth,SIGNAL(sliderReleased()),this,SLOT(commonReleased())); + connect(ui->dDelay,SIGNAL(sliderReleased()),this,SLOT(commonReleased())); + + connect(ui->dCut,SIGNAL(valueChanged(int)),this,SLOT(commonChanged())); + connect(ui->dReso,SIGNAL(valueChanged(int)),this,SLOT(commonChanged())); + connect(ui->dReverb,SIGNAL(valueChanged(int)),this,SLOT(commonChanged())); + connect(ui->dChorus,SIGNAL(valueChanged(int)),this,SLOT(commonChanged())); + connect(ui->dVol,SIGNAL(valueChanged(int)),this,SLOT(commonChanged())); + connect(ui->dPan,SIGNAL(valueChanged(int)),this,SLOT(commonChanged())); + connect(ui->dAttack,SIGNAL(valueChanged(int)),this,SLOT(commonChanged())); + connect(ui->dDecay,SIGNAL(valueChanged(int)),this,SLOT(commonChanged())); + connect(ui->dRelease,SIGNAL(valueChanged(int)),this,SLOT(commonChanged())); + connect(ui->dRate,SIGNAL(valueChanged(int)),this,SLOT(commonChanged())); + connect(ui->dDepth,SIGNAL(valueChanged(int)),this,SLOT(commonChanged())); + connect(ui->dDelay,SIGNAL(valueChanged(int)),this,SLOT(commonChanged())); +} + +void qmpChannelEditor::disconnectSlots() +{ + disconnect(ui->dCut,SIGNAL(sliderPressed()),this,SLOT(commonPressed())); + disconnect(ui->dReso,SIGNAL(sliderPressed()),this,SLOT(commonPressed())); + disconnect(ui->dReverb,SIGNAL(sliderPressed()),this,SLOT(commonPressed())); + disconnect(ui->dChorus,SIGNAL(sliderPressed()),this,SLOT(commonPressed())); + disconnect(ui->dVol,SIGNAL(sliderPressed()),this,SLOT(commonPressed())); + disconnect(ui->dPan,SIGNAL(sliderPressed()),this,SLOT(commonPressed())); + disconnect(ui->dAttack,SIGNAL(sliderPressed()),this,SLOT(commonPressed())); + disconnect(ui->dDecay,SIGNAL(sliderPressed()),this,SLOT(commonPressed())); + disconnect(ui->dRelease,SIGNAL(sliderPressed()),this,SLOT(commonPressed())); + disconnect(ui->dRate,SIGNAL(sliderPressed()),this,SLOT(commonPressed())); + disconnect(ui->dDepth,SIGNAL(sliderPressed()),this,SLOT(commonPressed())); + disconnect(ui->dDelay,SIGNAL(sliderPressed()),this,SLOT(commonPressed())); + + disconnect(ui->dCut,SIGNAL(sliderReleased()),this,SLOT(commonReleased())); + disconnect(ui->dReso,SIGNAL(sliderReleased()),this,SLOT(commonReleased())); + disconnect(ui->dReverb,SIGNAL(sliderReleased()),this,SLOT(commonReleased())); + disconnect(ui->dChorus,SIGNAL(sliderReleased()),this,SLOT(commonReleased())); + disconnect(ui->dVol,SIGNAL(sliderReleased()),this,SLOT(commonReleased())); + disconnect(ui->dPan,SIGNAL(sliderReleased()),this,SLOT(commonReleased())); + disconnect(ui->dAttack,SIGNAL(sliderReleased()),this,SLOT(commonReleased())); + disconnect(ui->dDecay,SIGNAL(sliderReleased()),this,SLOT(commonReleased())); + disconnect(ui->dRelease,SIGNAL(sliderReleased()),this,SLOT(commonReleased())); + disconnect(ui->dRate,SIGNAL(sliderReleased()),this,SLOT(commonReleased())); + disconnect(ui->dDepth,SIGNAL(sliderReleased()),this,SLOT(commonReleased())); + disconnect(ui->dDelay,SIGNAL(sliderReleased()),this,SLOT(commonReleased())); + + disconnect(ui->dCut,SIGNAL(valueChanged(int)),this,SLOT(commonChanged())); + disconnect(ui->dReso,SIGNAL(valueChanged(int)),this,SLOT(commonChanged())); + disconnect(ui->dReverb,SIGNAL(valueChanged(int)),this,SLOT(commonChanged())); + disconnect(ui->dChorus,SIGNAL(valueChanged(int)),this,SLOT(commonChanged())); + disconnect(ui->dVol,SIGNAL(valueChanged(int)),this,SLOT(commonChanged())); + disconnect(ui->dPan,SIGNAL(valueChanged(int)),this,SLOT(commonChanged())); + disconnect(ui->dAttack,SIGNAL(valueChanged(int)),this,SLOT(commonChanged())); + disconnect(ui->dDecay,SIGNAL(valueChanged(int)),this,SLOT(commonChanged())); + disconnect(ui->dRelease,SIGNAL(valueChanged(int)),this,SLOT(commonChanged())); + disconnect(ui->dRate,SIGNAL(valueChanged(int)),this,SLOT(commonChanged())); + disconnect(ui->dDepth,SIGNAL(valueChanged(int)),this,SLOT(commonChanged())); + disconnect(ui->dDelay,SIGNAL(valueChanged(int)),this,SLOT(commonChanged())); +} diff --git a/qmidiplayer.src.d/qmpchanneleditor.hpp b/qmidiplayer.src.d/qmpchanneleditor.hpp new file mode 100644 index 0000000..0653af5 --- /dev/null +++ b/qmidiplayer.src.d/qmpchanneleditor.hpp @@ -0,0 +1,42 @@ +#ifndef QMPCHANNELEDITOR_H +#define QMPCHANNELEDITOR_H + +#include +#include +#include +#include "qdialskulpturestyle.hpp" + +namespace Ui { + class qmpChannelEditor; +} + +class qmpChannelEditor:public QDialog +{ + Q_OBJECT + + public: + explicit qmpChannelEditor(QWidget *parent=0); + ~qmpChannelEditor(); + protected: + void showEvent(QShowEvent *e); + void closeEvent(QCloseEvent *e); + public slots: + void setupWindow(int chid=-1); + + private slots: + void commonPressed(); + void commonReleased(); + void commonChanged(); + void on_pbChLeft_clicked(); + void on_pbChRight_clicked(); + + private: + Ui::qmpChannelEditor *ui; + int ch,knobpressed; + void sendCC(); + void connectSlots(); + void disconnectSlots(); + QCommonStyle* styl; +}; + +#endif // QMPCHANNELEDITOR_H diff --git a/qmidiplayer.src.d/qmpchanneleditor.ui b/qmidiplayer.src.d/qmpchanneleditor.ui new file mode 100644 index 0000000..49e8c8e --- /dev/null +++ b/qmidiplayer.src.d/qmpchanneleditor.ui @@ -0,0 +1,602 @@ + + + qmpChannelEditor + + + + 0 + 0 + 422 + 300 + + + + + 422 + 300 + + + + + 422 + 300 + + + + Dialog + + + + + 10 + 10 + 21 + 21 + + + + < + + + + + + 30 + 10 + 21 + 20 + + + + 1 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + 50 + 10 + 21 + 21 + + + + > + + + + + + 90 + 10 + 261 + 51 + + + + + 16 + + + + Yamaha Grand Piano + + + + + + 10 + 30 + 81 + 20 + + + + BK: 0 + + + + + + 10 + 50 + 81 + 20 + + + + PC: 0 + + + + + + 0 + 70 + 141 + 101 + + + + Filters + + + + + 70 + 80 + 66 + 20 + + + + Res. 64 + + + Qt::AlignCenter + + + + + + 80 + 30 + 50 + 51 + + + + 127 + + + 64 + + + true + + + + + + 10 + 30 + 50 + 51 + + + + 127 + + + 64 + + + true + + + + + + 0 + 80 + 71 + 20 + + + + Cut. 64 + + + Qt::AlignCenter + + + + + + + 140 + 70 + 141 + 101 + + + + Effects + + + + + 70 + 80 + 66 + 20 + + + + Chr. 64 + + + Qt::AlignCenter + + + + + + 80 + 30 + 50 + 51 + + + + 127 + + + 64 + + + true + + + + + + 10 + 30 + 50 + 51 + + + + 127 + + + 64 + + + true + + + + + + 0 + 80 + 71 + 20 + + + + Rev. 64 + + + Qt::AlignCenter + + + + + + + 0 + 170 + 211 + 101 + + + + Envelope + + + + + 70 + 80 + 66 + 20 + + + + Dec. 64 + + + Qt::AlignCenter + + + + + + 80 + 30 + 50 + 51 + + + + 127 + + + 64 + + + true + + + + + + 10 + 30 + 50 + 51 + + + + 127 + + + 64 + + + true + + + + + + 0 + 80 + 71 + 20 + + + + Atk. 64 + + + Qt::AlignCenter + + + + + + 150 + 30 + 50 + 51 + + + + 127 + + + 64 + + + true + + + + + + 140 + 80 + 66 + 20 + + + + Rel. 64 + + + Qt::AlignCenter + + + + + + + 210 + 170 + 211 + 101 + + + + Vibrato + + + + + 70 + 80 + 66 + 20 + + + + Dep. 64 + + + Qt::AlignCenter + + + + + + 80 + 30 + 50 + 51 + + + + 127 + + + 64 + + + true + + + + + + 10 + 30 + 50 + 51 + + + + 127 + + + 64 + + + true + + + + + + 0 + 80 + 71 + 20 + + + + Rate 64 + + + Qt::AlignCenter + + + + + + 150 + 30 + 50 + 51 + + + + 127 + + + 64 + + + true + + + + + + 140 + 80 + 66 + 20 + + + + Del. 64 + + + Qt::AlignCenter + + + + + + + 280 + 70 + 141 + 101 + + + + Mixer + + + + + 70 + 80 + 66 + 20 + + + + Pan. C + + + Qt::AlignCenter + + + + + + 80 + 30 + 50 + 51 + + + + 127 + + + 64 + + + true + + + + + + 0 + 80 + 66 + 20 + + + + Vol. 127 + + + Qt::AlignCenter + + + + + + 10 + 30 + 50 + 51 + + + + 127 + + + 127 + + + true + + + + + + + diff --git a/qmidiplayer.src.d/qmpchannelswindow.cpp b/qmidiplayer.src.d/qmpchannelswindow.cpp new file mode 100644 index 0000000..a9cf60e --- /dev/null +++ b/qmidiplayer.src.d/qmpchannelswindow.cpp @@ -0,0 +1,132 @@ +#include +#include +#include +#include "qmpchannelswindow.hpp" +#include "ui_qmpchannelswindow.h" +#include "qmpmainwindow.hpp" + +qmpChannelsWindow::qmpChannelsWindow(QWidget *parent) : + QDialog(parent), + ui(new Ui::qmpChannelsWindow) +{ + ui->setupUi(this); + pselectw=new qmpPresetSelector(this); + ceditw=new qmpChannelEditor(this); + connect(this,SIGNAL(dialogClosing()),parent,SLOT(dialogClosed())); + for(int i=0;i<16;++i) + { + ui->twChannels->setCellWidget(i,0,new QCheckBox("")); + connect(ui->twChannels->cellWidget(i,0),SIGNAL(stateChanged(int)),this,SLOT(channelMSChanged())); + ui->twChannels->setCellWidget(i,1,new QCheckBox("")); + connect(ui->twChannels->cellWidget(i,1),SIGNAL(stateChanged(int)),this,SLOT(channelMSChanged())); + ui->twChannels->setCellWidget(i,2,new QComboBox()); + QComboBox *cb=(QComboBox*)ui->twChannels->cellWidget(i,2); + //stub + cb->addItem("Internal FluidSynth"); + ui->twChannels->setCellWidget(i,3,new QDCLabel("")); + ((QDCLabel*)ui->twChannels->cellWidget(i,3))->setID(i); + connect(ui->twChannels->cellWidget(i,3),SIGNAL(onDoubleClick(int)),this,SLOT(showPresetWindow(int))); + ui->twChannels->setCellWidget(i,4,new QDCPushButton("...")); + ((QDCLabel*)ui->twChannels->cellWidget(i,4))->setID(i); + connect(ui->twChannels->cellWidget(i,4),SIGNAL(onClick(int)),this,SLOT(showChannelEditorWindow(int))); + } + ui->twChannels->setColumnWidth(0,32); + ui->twChannels->setColumnWidth(1,32); + ui->twChannels->setColumnWidth(2,192); + ui->twChannels->setColumnWidth(3,192); + ui->twChannels->setColumnWidth(4,32); +} + +void qmpChannelsWindow::showEvent(QShowEvent *event) +{ + if(qmpSettingsWindow::getSettingsIntf()->value("Behavior/DialogStatus","").toInt()) + { + qmpSettingsWindow::getSettingsIntf()->setValue("DialogStatus/ChnlWShown",1); + } + event->accept(); +} + +void qmpChannelsWindow::closeEvent(QCloseEvent *event) +{ + setVisible(false); + if(!qmpMainWindow::getInstance()->isFinalizing()&&qmpSettingsWindow::getSettingsIntf()->value("Behavior/DialogStatus","").toInt()) + { + qmpSettingsWindow::getSettingsIntf()->setValue("DialogStatus/ChnlWShown",0); + } + emit dialogClosing(); + event->accept(); +} + +void qmpChannelsWindow::moveEvent(QMoveEvent *event) +{ + if(qmpSettingsWindow::getSettingsIntf()->value("Behavior/DialogStatus","").toInt()) + { + qmpSettingsWindow::getSettingsIntf()->setValue("DialogStatus/ChnlW",event->pos()); + } +} + +void qmpChannelsWindow::channelWindowsUpdate() +{ + if(qmpMainWindow::getInstance()->getPlayer()->isFinished()) + { + for(int i=0;i<16;++i) + ((QLabel*)ui->twChannels->cellWidget(i,3))->setText(""); + return; + } + for(int i=0;i<16;++i) + { + char data[128],nm[24]; + int b,p; + qmpMainWindow::getInstance()->getPlayer()->getChannelPreset(i,&b,&p,nm); + sprintf(data,"%d:%d %s",b,p,nm); + ((QLabel*)ui->twChannels->cellWidget(i,3))->setText(data); + } +} + +void qmpChannelsWindow::channelMSChanged() +{ + for(int i=0;i<16;++i) + { + QCheckBox *m,*s; + m=(QCheckBox*)ui->twChannels->cellWidget(i,0); + s=(QCheckBox*)ui->twChannels->cellWidget(i,1); + if(m->isChecked()&&s->isChecked())s->setChecked(false); + qmpMainWindow::getInstance()->getPlayer()->setMute(i,m->isChecked()); + qmpMainWindow::getInstance()->getPlayer()->setSolo(i,s->isChecked()); + } +} + +qmpChannelsWindow::~qmpChannelsWindow() +{ + delete ui; +} + +void qmpChannelsWindow::on_pbUnmute_clicked() +{ + for(int i=0;i<16;++i) + { + ((QCheckBox*)ui->twChannels->cellWidget(i,0))->setChecked(false); + qmpMainWindow::getInstance()->getPlayer()->setMute(i,false); + } +} + +void qmpChannelsWindow::on_pbUnsolo_clicked() +{ + for(int i=0;i<16;++i) + { + ((QCheckBox*)ui->twChannels->cellWidget(i,1))->setChecked(false); + qmpMainWindow::getInstance()->getPlayer()->setSolo(i,false); + } +} + +void qmpChannelsWindow::showPresetWindow(int chid) +{ + pselectw->show(); + pselectw->setupWindow(chid); +} + +void qmpChannelsWindow::showChannelEditorWindow(int chid) +{ + ceditw->show(); + ceditw->setupWindow(chid); +} diff --git a/qmidiplayer.src.d/qmpchannelswindow.hpp b/qmidiplayer.src.d/qmpchannelswindow.hpp new file mode 100644 index 0000000..f0591b6 --- /dev/null +++ b/qmidiplayer.src.d/qmpchannelswindow.hpp @@ -0,0 +1,71 @@ +#ifndef QMPCHANNELSWINDOW_H +#define QMPCHANNELSWINDOW_H + +#include +#include +#include +#include +#include +#include +#include "qmppresetselect.hpp" +#include "qmpchanneleditor.hpp" + +namespace Ui { + class qmpChannelsWindow; +} + +class QDCLabel:public QLabel +{ + Q_OBJECT + private: + int id; + protected: + void mouseDoubleClickEvent(QMouseEvent *event){event->accept();emit onDoubleClick(id);} + public: + QDCLabel(QString s):QLabel(s){id=-1;} + void setID(int _id){id=_id;} + signals: + void onDoubleClick(int id); +}; + +class QDCPushButton:public QPushButton +{ + Q_OBJECT + private: + int id; + protected: + void mousePressEvent(QMouseEvent *event){QPushButton::mousePressEvent(event);emit onClick(id);} + public: + QDCPushButton(QString s):QPushButton(s){id=-1;} + void setID(int _id){id=_id;} + signals: + void onClick(int id); +}; + +class qmpChannelsWindow:public QDialog +{ + Q_OBJECT + + public: + explicit qmpChannelsWindow(QWidget *parent = 0); + ~qmpChannelsWindow(); + void showEvent(QShowEvent *event); + void closeEvent(QCloseEvent *event); + void moveEvent(QMoveEvent *event); + signals: + void dialogClosing(); + public slots: + void channelWindowsUpdate(); + void channelMSChanged(); + void showPresetWindow(int chid); + void showChannelEditorWindow(int chid); + void on_pbUnmute_clicked(); + void on_pbUnsolo_clicked(); + + private: + Ui::qmpChannelsWindow *ui; + qmpPresetSelector *pselectw; + qmpChannelEditor *ceditw; +}; + +#endif // QMPCHANNELSWINDOW_H diff --git a/qmidiplayer.src.d/qmpchannelswindow.ui b/qmidiplayer.src.d/qmpchannelswindow.ui new file mode 100644 index 0000000..a8b43cb --- /dev/null +++ b/qmidiplayer.src.d/qmpchannelswindow.ui @@ -0,0 +1,146 @@ + + + qmpChannelsWindow + + + + 0 + 0 + 580 + 410 + + + + + 580 + 410 + + + + + 580 + 16777215 + + + + Channels + + + + + + + + + 0 + 0 + + + + true + + + QAbstractItemView::NoSelection + + + false + + + 16 + + + 5 + + + + + + + + + + + + + + + + + + + + M + + + + + S + + + + + Device + + + + + Preset + + + + + ... + + + + + + + + + + + + + + + + + Save + + + + 16 + 16 + + + + + + + + Load + + + + + + + Unmute All + + + + + + + Unsolo All + + + + + + + + + + diff --git a/qmidiplayer.src.d/qmpefxwindow.cpp b/qmidiplayer.src.d/qmpefxwindow.cpp new file mode 100644 index 0000000..7d9c08e --- /dev/null +++ b/qmidiplayer.src.d/qmpefxwindow.cpp @@ -0,0 +1,198 @@ +#include +#include "qmpefxwindow.hpp" +#include "ui_qmpefxwindow.h" +#include "qmpmainwindow.hpp" + +qmpEfxWindow::qmpEfxWindow(QWidget *parent) : + QDialog(parent), + ui(new Ui::qmpEfxWindow) +{ + ui->setupUi(this);initialized=false; + styl=new QDialSkulptureStyle(); + QList dials=findChildren(); + for(int i=0;isetStyle(styl); + connect(this,SIGNAL(dialogClosing()),parent,SLOT(dialogClosed())); + //stub. read these from settings after the setting module is implemented + 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",FLUID_REVERB_DEFAULT_ROOMSIZE).toDouble(); + rd=settings->value("Effects/ReverbDamp",FLUID_REVERB_DEFAULT_DAMP).toDouble(); + rw=settings->value("Effects/ReverbWidth",FLUID_REVERB_DEFAULT_WIDTH).toDouble(); + rl=settings->value("Effects/ReverbLevel",FLUID_REVERB_DEFAULT_LEVEL).toDouble(); + + cfb=settings->value("Effects/ChorusFeedbk",FLUID_CHORUS_DEFAULT_N).toInt(); + cl=settings->value("Effects/ChorusLevel",FLUID_CHORUS_DEFAULT_LEVEL).toDouble(); + cr=settings->value("Effects/ChorusRate",FLUID_CHORUS_DEFAULT_SPEED).toDouble(); + cd=settings->value("Effects/ChorusDepth",FLUID_CHORUS_DEFAULT_DEPTH).toDouble(); + ct=settings->value("Effects/ChorusType",FLUID_CHORUS_DEFAULT_TYPE).toInt(); +} + +qmpEfxWindow::~qmpEfxWindow() +{ + delete styl; + delete ui; +} + +void qmpEfxWindow::closeEvent(QCloseEvent *event) +{ + setVisible(false); + if(!qmpMainWindow::getInstance()->isFinalizing()&&qmpSettingsWindow::getSettingsIntf()->value("Behavior/DialogStatus","").toInt()) + { + qmpSettingsWindow::getSettingsIntf()->setValue("DialogStatus/EfxWShown",0); + } + emit dialogClosing(); + event->accept(); +} + +void qmpEfxWindow::showEvent(QShowEvent *event) +{ + //CMidiPlayer* player=qmpMainWindow::getInstance()->getPlayer(); + //These parameters will never be modified outside this window... + /*if(initialized) + { + player->getReverbPara(&rr,&rd,&rw,&rl); + player->getChorusPara(&cfb,&cl,&cr,&cd,&ct); + }*/ + ui->sbRoom->setValue((int)round(rr*100));ui->dRoom->setValue((int)round(rr*100)); + ui->sbDamp->setValue((int)round(rd*100));ui->dDamp->setValue((int)round(rd*100)); + ui->sbWidth->setValue((int)round(rw*100));ui->dWidth->setValue((int)round(rw*100)); + ui->sbLevelR->setValue((int)round(rl*100));ui->dLevelR->setValue((int)round(rl*100)); + + ui->sbFeedBack->setValue(cfb);ui->dFeedBack->setValue(cfb); + ui->sbRate->setValue(cr);ui->dRate->setValue((int)round(cr*100)); + ui->sbDepth->setValue(cd);ui->dDepth->setValue((int)round(cd*10)); + ui->sbLevelC->setValue((int)round(cl*100));ui->dLevelC->setValue((int)round(cl*100)); + 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("Behavior/DialogStatus","").toInt()) + { + qmpSettingsWindow::getSettingsIntf()->setValue("DialogStatus/EfxWShown",1); + } + event->accept(); +} + +void qmpEfxWindow::moveEvent(QMoveEvent *event) +{ + if(qmpSettingsWindow::getSettingsIntf()->value("Behavior/DialogStatus","").toInt()) + { + qmpSettingsWindow::getSettingsIntf()->setValue("DialogStatus/EfxW",event->pos()); + } +} + +void qmpEfxWindow::sendEfxChange() +{ + if(!qmpMainWindow::getInstance()||!initialized)return; + rr=ui->sbRoom->value()/100.;rd=ui->sbDamp->value()/100.; + rw=ui->sbWidth->value()/100.;rl=ui->sbLevelR->value()/100.; + ct=ui->rbSine->isChecked()?FLUID_CHORUS_MOD_SINE:FLUID_CHORUS_MOD_TRIANGLE; + cfb=ui->sbFeedBack->value();cl=ui->sbLevelC->value()/100.; + cr=ui->sbRate->value();cd=ui->sbDepth->value(); + CMidiPlayer* player=qmpMainWindow::getInstance()->getPlayer(); + player->setReverbPara(ui->cbEnabledR->isChecked()?1:0,rr,rd,rw,rl); + player->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); +} + +void qmpEfxWindow::dailValueChange() +{ + if(!initialized)return; + ui->sbRoom->setValue(ui->dRoom->value()); + ui->sbDamp->setValue(ui->dDamp->value()); + ui->sbWidth->setValue(ui->dWidth->value()); + ui->sbLevelR->setValue(ui->dLevelR->value()); + ui->sbFeedBack->setValue(ui->dFeedBack->value()); + ui->sbRate->setValue(ui->dRate->value()/100.); + ui->sbDepth->setValue(ui->dDepth->value()/10.); + ui->sbLevelC->setValue(ui->dLevelC->value()); + sendEfxChange(); +} + +void qmpEfxWindow::spinValueChange() +{ + if(!initialized)return; + ui->dRoom->setValue(ui->sbRoom->value()); + ui->dDamp->setValue(ui->sbDamp->value()); + ui->dWidth->setValue(ui->sbWidth->value()); + ui->dLevelR->setValue(ui->sbLevelR->value()); + ui->dFeedBack->setValue(ui->sbFeedBack->value()); + ui->dRate->setValue((int)(ui->sbRate->value()*100)); + ui->dDepth->setValue((int)(ui->sbDepth->value()*10)); + ui->dLevelC->setValue(ui->sbLevelC->value()); + sendEfxChange(); +} + +void qmpEfxWindow::on_dRoom_valueChanged() +{dailValueChange();} + +void qmpEfxWindow::on_dDamp_valueChanged() +{dailValueChange();} + +void qmpEfxWindow::on_dWidth_valueChanged() +{dailValueChange();} + +void qmpEfxWindow::on_dLevelR_valueChanged() +{dailValueChange();} + +void qmpEfxWindow::on_dFeedBack_valueChanged() +{dailValueChange();} + +void qmpEfxWindow::on_dRate_valueChanged() +{dailValueChange();} + +void qmpEfxWindow::on_dDepth_valueChanged() +{dailValueChange();} + +void qmpEfxWindow::on_dLevelC_valueChanged() +{dailValueChange();} + +void qmpEfxWindow::on_sbRoom_valueChanged(QString s) +{s=QString();spinValueChange();} + +void qmpEfxWindow::on_sbDamp_valueChanged(QString s) +{s=QString();spinValueChange();} + +void qmpEfxWindow::on_sbWidth_valueChanged(QString s) +{s=QString();spinValueChange();} + +void qmpEfxWindow::on_sbLevelR_valueChanged(QString s) +{s=QString();spinValueChange();} + +void qmpEfxWindow::on_sbFeedBack_valueChanged(QString s) +{s=QString();spinValueChange();} + +void qmpEfxWindow::on_sbRate_valueChanged(QString s) +{s=QString();spinValueChange();} + +void qmpEfxWindow::on_sbDepth_valueChanged(QString s) +{s=QString();spinValueChange();} + +void qmpEfxWindow::on_sbLevelC_valueChanged(QString s) +{s=QString();spinValueChange();} + +void qmpEfxWindow::on_cbEnabledC_stateChanged() +{sendEfxChange();} + +void qmpEfxWindow::on_cbEnabledR_stateChanged() +{sendEfxChange();} + +void qmpEfxWindow::on_rbSine_toggled() +{sendEfxChange();} + +void qmpEfxWindow::on_rbTriangle_toggled() +{sendEfxChange();} diff --git a/qmidiplayer.src.d/qmpefxwindow.hpp b/qmidiplayer.src.d/qmpefxwindow.hpp new file mode 100644 index 0000000..2a080f0 --- /dev/null +++ b/qmidiplayer.src.d/qmpefxwindow.hpp @@ -0,0 +1,62 @@ +#ifndef QMPEFXWINDOW_HPP +#define QMPEFXWINDOW_HPP + +#include +#include +#include +#include + +#include "qdialskulpturestyle.hpp" + +namespace Ui { + class qmpEfxWindow; +} + +class qmpEfxWindow : public QDialog +{ + Q_OBJECT + + public: + explicit qmpEfxWindow(QWidget *parent=0); + ~qmpEfxWindow(); + void closeEvent(QCloseEvent *event); + void showEvent(QShowEvent *event); + void moveEvent(QMoveEvent *event); + void sendEfxChange(); + + signals: + void dialogClosing(); + + private slots: + void on_dRoom_valueChanged(); + void on_dDamp_valueChanged(); + void on_dWidth_valueChanged(); + void on_dLevelR_valueChanged(); + void on_dFeedBack_valueChanged(); + void on_dRate_valueChanged(); + void on_dDepth_valueChanged(); + void on_dLevelC_valueChanged(); + void on_sbRoom_valueChanged(QString s); + void on_sbDamp_valueChanged(QString s); + void on_sbWidth_valueChanged(QString s); + void on_sbLevelR_valueChanged(QString s); + void on_sbFeedBack_valueChanged(QString s); + void on_sbRate_valueChanged(QString s); + void on_sbDepth_valueChanged(QString s); + void on_sbLevelC_valueChanged(QString s); + void on_cbEnabledC_stateChanged(); + void on_cbEnabledR_stateChanged(); + void on_rbSine_toggled(); + void on_rbTriangle_toggled(); + + private: + void dailValueChange(); + void spinValueChange(); + Ui::qmpEfxWindow *ui; + double rr,rd,rw,rl; + int cfb,ct,initialized; + double cl,cr,cd; + QCommonStyle* styl; +}; + +#endif // QMPEFXWINDOW_HPP diff --git a/qmidiplayer.src.d/qmpefxwindow.ui b/qmidiplayer.src.d/qmpefxwindow.ui new file mode 100644 index 0000000..4a1e0c6 --- /dev/null +++ b/qmidiplayer.src.d/qmpefxwindow.ui @@ -0,0 +1,478 @@ + + + qmpEfxWindow + + + + 0 + 0 + 546 + 177 + + + + + 546 + 177 + + + + + 546 + 177 + + + + Effects + + + + + + Reverb + + + + + 80 + 4 + 21 + 24 + + + + + + + + + + 10 + 30 + 50 + 51 + + + + 120 + + + true + + + + + + 200 + 30 + 50 + 51 + + + + 100 + + + true + + + + + + 10 + 103 + 50 + 51 + + + + 100 + + + true + + + + + + 200 + 103 + 50 + 51 + + + + 100 + + + true + + + + + + 60 + 30 + 41 + 20 + + + + Room + + + + + + 60 + 50 + 51 + 21 + + + + 120 + + + + + + 140 + 30 + 51 + 20 + + + + Damp + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + 140 + 50 + 56 + 21 + + + + 100 + + + + + + 60 + 100 + 51 + 20 + + + + Width + + + + + + 60 + 120 + 56 + 21 + + + + 100 + + + + + + 145 + 100 + 51 + 20 + + + + Level + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + 140 + 120 + 56 + 21 + + + + 100 + + + + + + + + Chorus + + + + + 80 + 4 + 21 + 24 + + + + + + + + + + 10 + 30 + 50 + 51 + + + + 99 + + + true + + + + + + 200 + 30 + 50 + 51 + + + + 29 + + + 500 + + + 29 + + + true + + + + + + 10 + 103 + 50 + 51 + + + + 210 + + + true + + + + + + 200 + 103 + 50 + 51 + + + + 100 + + + true + + + + + + 60 + 30 + 71 + 20 + + + + Feedback + + + + + + 60 + 50 + 51 + 21 + + + + 99 + + + + + + 140 + 30 + 51 + 20 + + + + Rate + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + 60 + 100 + 51 + 20 + + + + Depth + + + + + + 145 + 100 + 51 + 20 + + + + Level + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + 140 + 120 + 56 + 21 + + + + 100 + + + + + + 137 + 50 + 61 + 21 + + + + 0.290000000000000 + + + 5.000000000000000 + + + 0.100000000000000 + + + + + + 35 + 77 + 41 + 20 + + + + LFO + + + + + + 70 + 77 + 61 + 20 + + + + Sine + + + + + + 145 + 77 + 91 + 20 + + + + Trian&gle + + + + + + 60 + 120 + 51 + 21 + + + + 1 + + + 21.000000000000000 + + + 0.100000000000000 + + + + + + + + + diff --git a/qmidiplayer.src.d/qmphelpwindow.cpp b/qmidiplayer.src.d/qmphelpwindow.cpp new file mode 100644 index 0000000..10cf083 --- /dev/null +++ b/qmidiplayer.src.d/qmphelpwindow.cpp @@ -0,0 +1,31 @@ +#include +#include "qmphelpwindow.hpp" +#include "ui_qmphelpwindow.h" + +qmpHelpWindow::qmpHelpWindow(QWidget *parent) : + QDialog(parent), + ui(new Ui::qmpHelpWindow) +{ + ui->setupUi(this); + ui->textBrowser->setSearchPaths(QStringList(QString(":/doc"))+QStringList(QString(":/img"))); + ui->textBrowser->setSource(QUrl("qrc:///doc/index.html")); +} + +qmpHelpWindow::~qmpHelpWindow() +{ + delete ui; +} + +void qmpHelpWindow::on_textBrowser_sourceChanged(const QUrl &src) +{ + if(src.fileName()==QString("version.html")) + { + QString s=ui->textBrowser->toHtml(); + s.replace("CT_QT_VERSION_STR",QT_VERSION_STR); + s.replace("RT_QT_VERSION_STR",qVersion()); + s.replace("CT_FLUIDSYNTH_VERSION",FLUIDSYNTH_VERSION); + s.replace("RT_FLUIDSYNTH_VERSION",fluid_version_str()); + s.replace("APP_VERSION",APP_VERSION); + ui->textBrowser->setHtml(s); + } +} diff --git a/qmidiplayer.src.d/qmphelpwindow.hpp b/qmidiplayer.src.d/qmphelpwindow.hpp new file mode 100644 index 0000000..c2052b2 --- /dev/null +++ b/qmidiplayer.src.d/qmphelpwindow.hpp @@ -0,0 +1,26 @@ +#ifndef QMPHELPWINDOW_H +#define QMPHELPWINDOW_H + +#include +#define APP_VERSION "0.7.0" + +namespace Ui { + class qmpHelpWindow; +} + +class qmpHelpWindow : public QDialog +{ + Q_OBJECT + + public: + explicit qmpHelpWindow(QWidget *parent = 0); + ~qmpHelpWindow(); + + private slots: + void on_textBrowser_sourceChanged(const QUrl &src); + + private: + Ui::qmpHelpWindow *ui; +}; + +#endif // QMPHELPWINDOW_H diff --git a/qmidiplayer.src.d/qmphelpwindow.ui b/qmidiplayer.src.d/qmphelpwindow.ui new file mode 100644 index 0000000..fd21b5f --- /dev/null +++ b/qmidiplayer.src.d/qmphelpwindow.ui @@ -0,0 +1,34 @@ + + + qmpHelpWindow + + + + 0 + 0 + 640 + 360 + + + + + 640 + 360 + + + + Help + + + + + + true + + + + + + + + diff --git a/qmidiplayer.src.d/qmpimidimapper.hpp b/qmidiplayer.src.d/qmpimidimapper.hpp new file mode 100644 index 0000000..d35dbb9 --- /dev/null +++ b/qmidiplayer.src.d/qmpimidimapper.hpp @@ -0,0 +1,16 @@ +#ifndef QMPIMIDIMAPPER_H +#define QMPIMIDIMAPPER_H +class qmpIMidiMapper +{ + virtual void deviceInit(int id)=0; + virtual void deviceDeinit(int id)=0; + virtual void noteOn(int ch,int key,int vel)=0; + virtual void noteOff(int ch,int key)=0; + virtual void ctrlChange(int ch,int cc,int val)=0; + virtual void progChange(int ch,int val)=0; + virtual void pitchBend(int ch,int val)=0; + virtual void sysEx(int length,const char* data)=0; + virtual static int enumDevices()=0; + virtual static char* deviceName(int id)=0; +}; +#endif // QMPIMIDIMAPPER_H diff --git a/qmidiplayer.src.d/qmpinfowindow.cpp b/qmidiplayer.src.d/qmpinfowindow.cpp new file mode 100644 index 0000000..689a756 --- /dev/null +++ b/qmidiplayer.src.d/qmpinfowindow.cpp @@ -0,0 +1,57 @@ +#include +#include "qmpinfowindow.hpp" +#include "ui_qmpinfowindow.h" +#include "qmpmainwindow.hpp" +#include "qmpsettingswindow.hpp" + +const char* minors="abebbbf c g d a e b f#c#g#d#a#"; +const char* majors="CbGbDbAbEbBbF C G D A E B F#C#"; +const char* standards="? GM GM2GS XG "; + +qmpInfoWindow::qmpInfoWindow(QWidget *parent) : + QDialog(parent), + ui(new Ui::qmpInfoWindow) +{ + ui->setupUi(this); +} + +qmpInfoWindow::~qmpInfoWindow() +{ + delete ui; +} + +void qmpInfoWindow::updateInfo() +{ + char str[256]; + CMidiPlayer* player=qmpMainWindow::getInstance()->getPlayer(); + QSettings* settings=qmpSettingsWindow::getSettingsIntf(); + ui->lbFileName->setText(QString("File name: ")+qmpMainWindow::getInstance()->getFileName()); + if(player->getTitle()) + { + if(settings->value("Midi/TextEncoding","").toString()!="Unicode") + ui->lbTitle->setText(QString("Title: ")+ + QTextCodec::codecForName(settings->value("Midi/TextEncoding","").toString().toStdString().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") + ui->lbCopyright->setText(QString("Copyright: ")+ + QTextCodec::codecForName(settings->value("Midi/TextEncoding","").toString().toStdString().c_str())->toUnicode(player->getCopyright())); + else + ui->lbCopyright->setText(QString("Copyright: ")+player->getCopyright()); + } + else ui->lbCopyright->setText(QString("Copyright: ")); + ui->lbTempo->setText(QString("Tempo: ")+QString::number(player->getTempo(),'g',5)); + int t,r;player->getCurrentKeySignature(&t);r=(int8_t)((t>>8)&0xFF)+7; + strncpy(str,t&0xFF?minors+2*r:majors+2*r,2);str[2]='\0'; + ui->lbKeySig->setText(QString("Key Sig.: ")+str); + player->getCurrentTimeSignature(&t,&r);sprintf(str,"Time Sig.: %d/%d",t,r); + ui->lbTimeSig->setText(str); + sprintf(str,"Note count: %u",player->getFileNoteCount()); + ui->lbNoteCount->setText(str); + strncpy(str,standards+player->getFileStandard()*3,3);str[3]='\0'; + ui->lbFileStandard->setText(QString("File standard: ")+str); +} diff --git a/qmidiplayer.src.d/qmpinfowindow.hpp b/qmidiplayer.src.d/qmpinfowindow.hpp new file mode 100644 index 0000000..9a1e389 --- /dev/null +++ b/qmidiplayer.src.d/qmpinfowindow.hpp @@ -0,0 +1,24 @@ +#ifndef QMPINFOWINDOW_HPP +#define QMPINFOWINDOW_HPP + +#include + +namespace Ui { + class qmpInfoWindow; +} + +class qmpInfoWindow : public QDialog +{ + Q_OBJECT + + public: + explicit qmpInfoWindow(QWidget *parent = 0); + ~qmpInfoWindow(); + public slots: + void updateInfo(); + + private: + Ui::qmpInfoWindow *ui; +}; + +#endif // QMPINFOWINDOW_HPP diff --git a/qmidiplayer.src.d/qmpinfowindow.ui b/qmidiplayer.src.d/qmpinfowindow.ui new file mode 100644 index 0000000..664531a --- /dev/null +++ b/qmidiplayer.src.d/qmpinfowindow.ui @@ -0,0 +1,91 @@ + + + qmpInfoWindow + + + + 0 + 0 + 400 + 142 + + + + + 400 + 142 + + + + File Information + + + + + + File name: + + + + + + + + + Tempo: + + + + + + + Key Sig.: + + + + + + + Time Sig.: + + + + + + + + + Title: + + + + + + + Copyright: + + + + + + + + + Note count: + + + + + + + File standard: + + + + + + + + + + diff --git a/qmidiplayer.src.d/qmpmainwindow.cpp b/qmidiplayer.src.d/qmpmainwindow.cpp new file mode 100644 index 0000000..453bd01 --- /dev/null +++ b/qmidiplayer.src.d/qmpmainwindow.cpp @@ -0,0 +1,510 @@ +#include +#include +#include +#include +#include +#include "qmpmainwindow.hpp" +#include "ui_qmpmainwindow.h" +#include "../common/qmpmidiplay.hpp" +#ifdef _WIN32 +#include +#endif + +qmpMainWindow* qmpMainWindow::ref=NULL; + +qmpMainWindow::qmpMainWindow(QWidget *parent) : + QMainWindow(parent), + ui(new Ui::qmpMainWindow) +{ + ui->setupUi(this); + ui->lbFileName->setText("");ref=this; + playing=false;stopped=true;dragging=false; + settingsw=new qmpSettingsWindow(this); + plistw=new qmpPlistWindow(this); + chnlw=new qmpChannelsWindow(this); + efxw=new qmpEfxWindow(this); + infow=new qmpInfoWindow(this); + helpw=new qmpHelpWindow(this); + timer=new QTimer(this); + fnA1=new QAction("File Information",ui->lbFileName); + fnA2=new QAction("Render to Wave",ui->lbFileName); + ui->lbFileName->addAction(fnA1); + ui->lbFileName->addAction(fnA2); + singleFS=qmpSettingsWindow::getSettingsIntf()->value("Behavior/SingleInstance",0).toInt(); + player=new CMidiPlayer(singleFS); + if(singleFS){player->fluidPreInitialize();playerSetup();player->fluidInitialize(); + for(int i=settingsw->getSFWidget()->count()-1;i>=0;--i) + player->pushSoundFont(settingsw->getSFWidget()->item(i)->text().toStdString().c_str());} + if(qmpSettingsWindow::getSettingsIntf()->value("Behavior/DialogStatus",0).toInt()) + { + QRect g=geometry(); + g.setTopLeft(qmpSettingsWindow::getSettingsIntf()->value("DialogStatus/MainW",QPoint(-999,-999)).toPoint()); + if(g.topLeft()!=QPoint(-999,-999))setGeometry(g); + else setGeometry(QStyle::alignedRect( + Qt::LeftToRight,Qt::AlignCenter,size(), + qApp->desktop()->availableGeometry())); + }show(); + if(qmpSettingsWindow::getSettingsIntf()->value("DialogStatus/PListWShown",0).toInt()) + {ui->pbPList->setChecked(true);on_pbPList_clicked();} + if(qmpSettingsWindow::getSettingsIntf()->value("DialogStatus/ChnlWShown",0).toInt()) + {ui->pbChannels->setChecked(true);on_pbChannels_clicked();} + if(qmpSettingsWindow::getSettingsIntf()->value("DialogStatus/EfxWShown",0).toInt()) + {ui->pbEfx->setChecked(true);on_pbEfx_clicked();} + ui->vsMasterVol->setValue(qmpSettingsWindow::getSettingsIntf()->value("Audio/Gain",50).toInt()); + connect(fnA1,SIGNAL(triggered()),this,SLOT(onfnA1())); + connect(fnA2,SIGNAL(triggered()),this,SLOT(onfnA2())); + connect(timer,SIGNAL(timeout()),this,SLOT(updateWidgets())); + connect(timer,SIGNAL(timeout()),chnlw,SLOT(channelWindowsUpdate())); + connect(timer,SIGNAL(timeout()),infow,SLOT(updateInfo())); +} + +qmpMainWindow::~qmpMainWindow() +{ + delete player; + delete timer; + delete ui; +} + +int qmpMainWindow::pharseArgs(int argc,char** argv) +{ + bool havemidi=false,loadfolder=false; + for(int i=1;iemptyList();} + if(loadfolder||qmpSettingsWindow::getSettingsIntf()->value("Behavior/LoadFolder",0).toInt()) + { + QDirIterator di(QUrl(argv[i]).adjusted(QUrl::RemoveFilename).toString()); + while(di.hasNext()) + { + QString c=di.next(); + if((c.endsWith(".mid")||c.endsWith(".midi"))&&fluid_is_midifile(c.toStdString().c_str())) + plistw->insertItem(c.toStdString().c_str()); + } + } + else + plistw->insertItem(argv[i]); + } + } + if(havemidi)on_pbPlayPause_clicked(); + return 0; +} + +void qmpMainWindow::closeEvent(QCloseEvent *event) +{ + on_pbStop_clicked();fin=true; + efxw->close();chnlw->close(); + plistw->close();infow->close(); + settingsw->close(); + delete helpw;helpw=NULL; + delete efxw;efxw=NULL; + delete chnlw;chnlw=NULL; + delete plistw;plistw=NULL; + delete infow;infow=NULL; + delete settingsw;settingsw=NULL; + event->accept(); +} + +void qmpMainWindow::moveEvent(QMoveEvent *event) +{ + if(qmpSettingsWindow::getSettingsIntf()->value("Behavior/DialogStatus","").toInt()) + { + qmpSettingsWindow::getSettingsIntf()->setValue("DialogStatus/MainW",event->pos()); + } +} +void qmpMainWindow::dropEvent(QDropEvent *event) +{ + QList l=event->mimeData()->urls(); + QStringList sl; + for(int i=0;iinsertItems(sl); +} +void qmpMainWindow::dragEnterEvent(QDragEnterEvent *event) +{ + //if(event->mimeData()->hasFormat("application/x-midi")) + event->acceptProposedAction(); +} + +void qmpMainWindow::updateWidgets() +{ + fnA2->setEnabled(stopped); + if(player->isFinished()&&playerTh) + { + if(!plistw->getRepeat()) + { + timer->stop();stopped=true;playing=false; + fnA2->setEnabled(stopped); + player->playerDeinit();playerTh->join(); + delete playerTh;playerTh=NULL; + if(singleFS)player->playerPanic(true); + chnlw->on_pbUnmute_clicked();chnlw->on_pbUnsolo_clicked(); + ui->pbPlayPause->setIcon(QIcon(":/img/play.png")); + ui->hsTimer->setValue(0); + ui->lbPolyphone->setText("Poly: 0/0"); + ui->lbCurTime->setText("00:00"); + } + else + { + timer->stop();player->playerDeinit();playerTh->join(); + delete playerTh;playerTh=NULL; + ui->hsTimer->setValue(0); + if(singleFS)player->playerPanic(true); + chnlw->on_pbUnmute_clicked();chnlw->on_pbUnsolo_clicked(); + QString fns=plistw->getNextItem(); + ui->lbFileName->setText(QUrl(fns).fileName()); + if(!player->playerLoadFile(fns.toStdString().c_str()))return; + char ts[100]; + sprintf(ts,"%02d:%02d",(int)player->getFtime()/60,(int)player->getFtime()%60); + ui->lbFinTime->setText(ts); + player->playerInit();if(!singleFS){playerSetup();player->fluidInitialize(); + for(int i=settingsw->getSFWidget()->count()-1;i>=0;--i) + player->pushSoundFont(settingsw->getSFWidget()->item(i)->text().toStdString().c_str());} + player->setGain(ui->vsMasterVol->value()/250.);efxw->sendEfxChange(); + player->setWaitVoice(qmpSettingsWindow::getSettingsIntf()->value("Midi/WaitVoice",1).toInt()); + playerTh=new std::thread(&CMidiPlayer::playerThread,player); +#ifdef _WIN32 + SetThreadPriority(playerTh->native_handle(),THREAD_PRIORITY_TIME_CRITICAL); +#endif + st=std::chrono::steady_clock::now();offset=0; + timer->start(100); + } + } + if(renderTh) + { + if(player->isFinished()) + { + renderTh->join();timer->stop(); + ui->centralWidget->setEnabled(true); + delete renderTh;renderTh=NULL; + player->rendererDeinit(); + if(singleFS){player->fluidPreInitialize();playerSetup();player->fluidInitialize();} + } + } + while(!player->isFinished()&&player->getTCeptr()>player->getStamp(ui->hsTimer->value()) + &&ui->hsTimer->value()<=100&&!dragging) + ui->hsTimer->setValue(ui->hsTimer->value()+1); + if(playing) + { + std::chrono::duration elapsed= + std::chrono::duration_cast>(std::chrono::steady_clock::now()-st); + char ts[100]; + sprintf(ts,"%02d:%02d",(int)(elapsed.count()+offset)/60,(int)(elapsed.count()+offset)%60); + ui->lbCurTime->setText(ts); + sprintf(ts,"Poly: %d/%d",player->getPolyphone(),player->getMaxPolyphone()); + ui->lbPolyphone->setText(ts); + } +} + +QString qmpMainWindow::getFileName(){return ui->lbFileName->text();} + +void qmpMainWindow::playerSetup() +{ + fluid_settings_t* fsettings=player->getFluidSettings(); + QSettings* settings=qmpSettingsWindow::getSettingsIntf(); + fluid_settings_setstr(fsettings,"audio.driver",settings->value("Audio/Driver","").toString().toStdString().c_str()); + fluid_settings_setint(fsettings,"audio.period-size",settings->value("Audio/BufSize","").toInt()); + fluid_settings_setint(fsettings,"audio.periods",settings->value("Audio/BufCnt","").toInt()); + fluid_settings_setstr(fsettings,"audio.sample-format",settings->value("Audio/Format","").toString().toStdString().c_str()); + fluid_settings_setint(fsettings,"synth.sample-rate",settings->value("Audio/Frequency","").toInt()); + fluid_settings_setint(fsettings,"synth.polyphony",settings->value("Audio/Polyphony","").toInt()); + fluid_settings_setint(fsettings,"synth.cpu-cores",settings->value("Audio/Threads","").toInt()); + char bsmode[4]; + if(!singleFS&&settings->value("Audio/AutoBS",1).toInt()&&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; + } + 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"); + } + fluid_settings_setstr(fsettings,"synth.midi-bank-select",bsmode); + player->sendSysX(settings->value("Midi/SendSysEx",1).toInt()); +} + +void qmpMainWindow::on_pbPlayPause_clicked() +{ + playing=!playing; + if(stopped) + { + QString fns=plistw->getFirstItem(); + if(!fns.length()) + { + plistw->on_pbAdd_clicked(); + fns=plistw->getFirstItem(); + if(!fns.length())return(void)(playing=false); + } + ui->lbFileName->setText(QUrl(fns).fileName()); + if(!player->playerLoadFile(fns.toStdString().c_str()))return; + char ts[100]; + sprintf(ts,"%02d:%02d",(int)player->getFtime()/60,(int)player->getFtime()%60); + ui->lbFinTime->setText(ts); + player->playerInit();if(!singleFS){playerSetup();player->fluidInitialize(); + for(int i=settingsw->getSFWidget()->count()-1;i>=0;--i) + player->pushSoundFont(settingsw->getSFWidget()->item(i)->text().toStdString().c_str());} + player->setGain(ui->vsMasterVol->value()/250.);efxw->sendEfxChange(); + player->setWaitVoice(qmpSettingsWindow::getSettingsIntf()->value("Midi/WaitVoice",1).toInt()); + playerTh=new std::thread(&CMidiPlayer::playerThread,player); +#ifdef _WIN32 + SetThreadPriority(playerTh->native_handle(),THREAD_PRIORITY_TIME_CRITICAL); +#endif + st=std::chrono::steady_clock::now();offset=0; + timer->start(100); + stopped=false; + } + else + { + if(!playing) + { + player->playerPanic(); + offset=ui->hsTimer->value()/100.*player->getFtime(); + } + else + { + st=std::chrono::steady_clock::now(); + player->setResumed(); + } + player->setTCpaused(!playing); + } + ui->pbPlayPause->setIcon(QIcon(playing?":/img/pause.png":":/img/play.png")); +} + +void qmpMainWindow::on_hsTimer_sliderPressed() +{ + dragging=true; +} + +void qmpMainWindow::on_hsTimer_sliderReleased() +{ + dragging=false; + if(playing) + { + if(ui->hsTimer->value()==100){on_pbNext_clicked();return;} + player->setTCeptr(player->getStamp(ui->hsTimer->value()),ui->hsTimer->value()); + player->playerPanic(); + offset=ui->hsTimer->value()/100.*player->getFtime(); + st=std::chrono::steady_clock::now(); + } + else + { + player->setTCeptr(player->getStamp(ui->hsTimer->value()),ui->hsTimer->value()); + offset=ui->hsTimer->value()/100.*player->getFtime(); + char ts[100]; + sprintf(ts,"%02d:%02d",(int)(offset)/60,(int)(offset)%60); + ui->lbCurTime->setText(ts); + } +} + +void qmpMainWindow::on_vsMasterVol_valueChanged() +{ + if(!stopped)player->setGain(ui->vsMasterVol->value()/250.); + qmpSettingsWindow::getSettingsIntf()->setValue("Audio/Gain",ui->vsMasterVol->value()); +} + +void qmpMainWindow::on_pbStop_clicked() +{ + if(!stopped) + { + timer->stop();stopped=true;playing=false; + player->playerDeinit();fnA2->setEnabled(stopped); + if(singleFS)player->playerPanic(true); + if(playerTh){playerTh->join();delete playerTh;playerTh=NULL;} + chnlw->on_pbUnmute_clicked();chnlw->on_pbUnsolo_clicked(); + ui->pbPlayPause->setIcon(QIcon(":/img/play.png")); + ui->hsTimer->setValue(0); + ui->lbPolyphone->setText("Poly: 0/0"); + ui->lbCurTime->setText("00:00"); + } +} + +void qmpMainWindow::dialogClosed() +{ + if(!plistw->isVisible())ui->pbPList->setChecked(false); + if(!chnlw->isVisible())ui->pbChannels->setChecked(false); + if(!efxw->isVisible())ui->pbEfx->setChecked(false); + if(!settingsw->isVisible())ui->pbSettings->setChecked(false); +} + +void qmpMainWindow::on_pbPList_clicked() +{ + if(ui->pbPList->isChecked()) + { + QRect g=plistw->geometry(); + g.setTopLeft(qmpSettingsWindow::getSettingsIntf()->value("DialogStatus/PListW",QPoint(-999,-999)).toPoint()); + if(g.topLeft()==QPoint(-999,-999)) + g.setTopLeft(window()->mapToGlobal(window()->rect().center())-plistw->rect().center()); + plistw->setGeometry(g); + plistw->show(); + }else plistw->close(); +} + +void qmpMainWindow::on_pbChannels_clicked() +{ + if(ui->pbChannels->isChecked()) + { + QRect g=chnlw->geometry(); + g.setTopLeft(qmpSettingsWindow::getSettingsIntf()->value("DialogStatus/ChnlW",QPoint(-999,-999)).toPoint()); + if(g.topLeft()==QPoint(-999,-999)) + g.setTopLeft(window()->mapToGlobal(window()->rect().center())-chnlw->rect().center()); + chnlw->setGeometry(g); + chnlw->show(); + }else chnlw->close(); +} + +void qmpMainWindow::on_pbPrev_clicked() +{ + timer->stop();player->playerDeinit(); + if(playerTh){playerTh->join();delete playerTh;playerTh=NULL;} + if(singleFS)player->playerPanic(true); + ui->hsTimer->setValue(0);chnlw->on_pbUnmute_clicked();chnlw->on_pbUnsolo_clicked(); + QString fns=plistw->getPrevItem();if(fns.length()==0)return on_pbStop_clicked(); + ui->lbFileName->setText(QUrl(fns).fileName()); + if(!player->playerLoadFile(fns.toStdString().c_str()))return; + char ts[100]; + sprintf(ts,"%02d:%02d",(int)player->getFtime()/60,(int)player->getFtime()%60); + ui->lbFinTime->setText(ts); + player->playerInit();if(!singleFS){playerSetup();player->fluidInitialize(); + for(int i=settingsw->getSFWidget()->count()-1;i>=0;--i) + player->pushSoundFont(settingsw->getSFWidget()->item(i)->text().toStdString().c_str());} + player->setGain(ui->vsMasterVol->value()/250.);efxw->sendEfxChange(); + player->setWaitVoice(qmpSettingsWindow::getSettingsIntf()->value("Midi/WaitVoice",1).toInt()); + playerTh=new std::thread(&CMidiPlayer::playerThread,player); +#ifdef _WIN32 + SetThreadPriority(playerTh->native_handle(),THREAD_PRIORITY_TIME_CRITICAL); +#endif + st=std::chrono::steady_clock::now();offset=0; + timer->start(100); +} + +void qmpMainWindow::on_pbNext_clicked() +{ + timer->stop();player->playerDeinit(); + if(playerTh){playerTh->join();delete playerTh;playerTh=NULL;} + if(singleFS)player->playerPanic(true); + ui->hsTimer->setValue(0);chnlw->on_pbUnmute_clicked();chnlw->on_pbUnsolo_clicked(); + QString fns=plistw->getNextItem();if(fns.length()==0)return on_pbStop_clicked(); + ui->lbFileName->setText(QUrl(fns).fileName()); + if(!player->playerLoadFile(fns.toStdString().c_str()))return; + char ts[100]; + sprintf(ts,"%02d:%02d",(int)player->getFtime()/60,(int)player->getFtime()%60); + ui->lbFinTime->setText(ts); + player->playerInit();if(!singleFS){playerSetup();player->fluidInitialize(); + for(int i=settingsw->getSFWidget()->count()-1;i>=0;--i) + player->pushSoundFont(settingsw->getSFWidget()->item(i)->text().toStdString().c_str());} + player->setGain(ui->vsMasterVol->value()/250.);efxw->sendEfxChange(); + player->setWaitVoice(qmpSettingsWindow::getSettingsIntf()->value("Midi/WaitVoice",1).toInt()); + playerTh=new std::thread(&CMidiPlayer::playerThread,player); +#ifdef _WIN32 + SetThreadPriority(playerTh->native_handle(),THREAD_PRIORITY_TIME_CRITICAL); +#endif + st=std::chrono::steady_clock::now();offset=0; + timer->start(100); +} + +void qmpMainWindow::selectionChanged() +{ + stopped=false;playing=true; + ui->pbPlayPause->setIcon(QIcon(":/img/pause.png")); + timer->stop();player->playerDeinit(); + if(playerTh){playerTh->join();delete playerTh;playerTh=NULL;} + if(singleFS)player->playerPanic(true); + ui->hsTimer->setValue(0); + chnlw->on_pbUnmute_clicked();chnlw->on_pbUnsolo_clicked(); + QString fns=plistw->getSelectedItem(); + ui->lbFileName->setText(QUrl(fns).fileName()); + if(!player->playerLoadFile(fns.toStdString().c_str()))return; + char ts[100]; + sprintf(ts,"%02d:%02d",(int)player->getFtime()/60,(int)player->getFtime()%60); + ui->lbFinTime->setText(ts); + player->playerInit();if(!singleFS){playerSetup();player->fluidInitialize(); + for(int i=settingsw->getSFWidget()->count()-1;i>=0;--i) + player->pushSoundFont(settingsw->getSFWidget()->item(i)->text().toStdString().c_str());} + player->setGain(ui->vsMasterVol->value()/250.);efxw->sendEfxChange(); + player->setWaitVoice(qmpSettingsWindow::getSettingsIntf()->value("Midi/WaitVoice",1).toInt()); + playerTh=new std::thread(&CMidiPlayer::playerThread,player); +#ifdef _WIN32 + SetThreadPriority(playerTh->native_handle(),THREAD_PRIORITY_TIME_CRITICAL); +#endif + st=std::chrono::steady_clock::now();offset=0; + timer->start(100); +} + +void qmpMainWindow::on_pbEfx_clicked() +{ + if(ui->pbEfx->isChecked()) + { + QRect g=efxw->geometry(); + g.setTopLeft(qmpSettingsWindow::getSettingsIntf()->value("DialogStatus/EfxW",QPoint(-999,-999)).toPoint()); + if(g.topLeft()==QPoint(-999,-999)) + g.setTopLeft(window()->mapToGlobal(window()->rect().center())-efxw->rect().center()); + efxw->setGeometry(g); + efxw->show(); + } + else efxw->close(); +} + +void qmpMainWindow::on_lbFileName_customContextMenuRequested(const QPoint &pos) +{ + QMenu menu(ui->lbFileName); + menu.addActions(ui->lbFileName->actions()); + menu.exec(this->pos()+ui->lbFileName->pos()+pos); +} + +void qmpMainWindow::onfnA1() +{ + infow->show(); +} + +void qmpMainWindow::onfnA2() +{ + if(singleFS)player->fluidDeinitialize(); + player->rendererLoadFile((plistw->getSelectedItem()+QString(".wav")).toStdString().c_str()); + playerSetup();player->rendererInit(plistw->getSelectedItem().toStdString().c_str()); + ui->centralWidget->setEnabled(false); + for(int i=settingsw->getSFWidget()->count()-1;i>=0;--i) + player->pushSoundFont(settingsw->getSFWidget()->item(i)->text().toStdString().c_str()); + player->setGain(ui->vsMasterVol->value()/250.);efxw->sendEfxChange();timer->start(100); + renderTh=new std::thread(&CMidiPlayer::rendererThread,player); +} + +void qmpMainWindow::on_pbSettings_clicked() +{ + if(ui->pbSettings->isChecked())settingsw->show();else settingsw->close(); +} + +void qmpMainWindow::on_pushButton_clicked() +{ + helpw->show(); +} diff --git a/qmidiplayer.src.d/qmpmainwindow.hpp b/qmidiplayer.src.d/qmpmainwindow.hpp new file mode 100644 index 0000000..517f792 --- /dev/null +++ b/qmidiplayer.src.d/qmpmainwindow.hpp @@ -0,0 +1,90 @@ +#ifndef QMPMAINWINDOW_H +#define QMPMAINWINDOW_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../common/qmpmidiplay.hpp" +#include "qmpplistwindow.hpp" +#include "qmpchannelswindow.hpp" +#include "qmpefxwindow.hpp" +#include "qmpinfowindow.hpp" +#include "qmpsettingswindow.hpp" +#include "qmphelpwindow.hpp" + +namespace Ui { + class qmpMainWindow; +} + +class qmpMainWindow:public QMainWindow +{ + Q_OBJECT + + public: + explicit qmpMainWindow(QWidget *parent = 0); + void closeEvent(QCloseEvent *event); + void moveEvent(QMoveEvent *event); + void dropEvent(QDropEvent *event); + void dragEnterEvent(QDragEnterEvent *event); + ~qmpMainWindow(); + CMidiPlayer* getPlayer(){return player;} + QTimer* getTimer(){return timer;} + bool isFinalizing(){return fin;} + QString getFileName(); + int pharseArgs(int argc,char** argv); + + private slots: + void on_pbPlayPause_clicked(); + void updateWidgets(); + void on_hsTimer_sliderPressed(); + void on_hsTimer_sliderReleased(); + void on_vsMasterVol_valueChanged(); + void on_pbStop_clicked(); + void on_pbPList_clicked(); + void on_pbPrev_clicked(); + void on_pbNext_clicked(); + void on_pbChannels_clicked(); + void on_pbEfx_clicked(); + void on_lbFileName_customContextMenuRequested(const QPoint &pos); + void on_pbSettings_clicked(); + void onfnA1(); + void onfnA2(); + + void on_pushButton_clicked(); + + public slots: + void dialogClosed(); + void selectionChanged(); + + private: + Ui::qmpMainWindow *ui; + QTimer *timer; + bool playing,stopped,dragging,fin,singleFS; + std::thread *playerTh=NULL; + std::thread *renderTh=NULL; + std::chrono::steady_clock::time_point st; + double offset; + CMidiPlayer *player; + qmpPlistWindow *plistw; + qmpChannelsWindow *chnlw; + qmpEfxWindow *efxw; + qmpInfoWindow *infow; + qmpSettingsWindow *settingsw; + qmpHelpWindow *helpw; + + QAction *fnA1,*fnA2; + void playerSetup(); + + private: + static qmpMainWindow* ref; + public: static qmpMainWindow* getInstance(){return ref;} +}; + +#endif // QMPMAINWINDOW_H diff --git a/qmidiplayer.src.d/qmpmainwindow.ui b/qmidiplayer.src.d/qmpmainwindow.ui new file mode 100644 index 0000000..0764e09 --- /dev/null +++ b/qmidiplayer.src.d/qmpmainwindow.ui @@ -0,0 +1,413 @@ + + + qmpMainWindow + + + + 0 + 0 + 435 + 245 + + + + + 435 + 245 + + + + + 435 + 245 + + + + true + + + QMidiPlayer + + + + :/img/qmidiplyr.png:/img/qmidiplyr.png + + + + + + 30 + 20 + 311 + 41 + + + + + 18 + + + + Qt::CustomContextMenu + + + somefile.mid + + + Qt::AlignCenter + + + + + + 20 + 90 + 321 + 20 + + + + 100 + + + 0 + + + Qt::Horizontal + + + + + + 20 + 110 + 61 + 36 + + + + + + + + :/img/play.png:/img/play.png + + + + 32 + 32 + + + + + + + 80 + 110 + 61 + 36 + + + + + + + + :/img/stop.png:/img/stop.png + + + + 32 + 32 + + + + + + + 140 + 110 + 61 + 36 + + + + + + + + :/img/prev.png:/img/prev.png + + + + 32 + 32 + + + + + + + 200 + 110 + 61 + 36 + + + + + + + + :/img/next.png:/img/next.png + + + + 32 + 32 + + + + + + + 280 + 110 + 61 + 36 + + + + + + + + :/img/settings.png:/img/settings.png + + + + 32 + 32 + + + + true + + + + + + 20 + 160 + 151 + 36 + + + + text-align:left + + + Channels + + + + :/img/channel.png:/img/channel.png + + + + 32 + 32 + + + + true + + + + + + 190 + 160 + 151 + 36 + + + + text-align:left + + + Playlist + + + + :/img/list.png:/img/list.png + + + + 32 + 32 + + + + true + + + false + + + false + + + + + + 20 + 200 + 151 + 36 + + + + text-align:left + + + Effects + + + + :/img/effects.png:/img/effects.png + + + + 32 + 32 + + + + true + + + + + + 190 + 200 + 151 + 36 + + + + text-align:left + + + Visualization + + + + :/img/visualization.png:/img/visualization.png + + + + 32 + 32 + + + + + + + 320 + 20 + 111 + 20 + + + + <html><head/><body><p>Poly: 0/0</p></body></html> + + + Qt::AlignCenter + + + + + + 370 + 50 + 20 + 160 + + + + 100 + + + 50 + + + Qt::Vertical + + + + + + 360 + 210 + 61 + 20 + + + + Master + + + + + + 20 + 70 + 66 + 20 + + + + 00:00 + + + + + + 270 + 70 + 66 + 20 + + + + 00:00 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + 0 + 0 + 21 + 21 + + + + ? + + + + + + + + + + diff --git a/qmidiplayer.src.d/qmpplistwindow.cpp b/qmidiplayer.src.d/qmpplistwindow.cpp new file mode 100644 index 0000000..8f04fc1 --- /dev/null +++ b/qmidiplayer.src.d/qmpplistwindow.cpp @@ -0,0 +1,308 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "qmpplistwindow.hpp" +#include "ui_qmpplistwindow.h" +#include "qmpmainwindow.hpp" + +qmpPlistWindow::qmpPlistWindow(QWidget *parent) : + QDialog(parent), + ui(new Ui::qmpPlistWindow) +{ + ui->setupUi(this); + connect(this,SIGNAL(dialogClosing()),parent,SLOT(dialogClosed())); + connect(this,SIGNAL(selectionChanging()),parent,SLOT(selectionChanged())); + repeat=0;shuffle=0; + if(qmpSettingsWindow::getSettingsIntf()->value("Behavior/RestorePlaylist","").toInt()) + { + QSettings* plist=new QSettings(QDir::homePath()+QString("/.config/qmpplist"), + QSettings::IniFormat); + int fc=plist->value("Playlist/FileCount",0).toInt(); + ui->lwFiles->clear();for(int i=1;i<=fc;++i) + ui->lwFiles->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(); + switch(shuffle) + { + case 1: + ui->pbShuffle->setIcon(QIcon(":/img/shuffle.png")); + ui->pbShuffle->setText("Shuffle On"); + break; + case 0: + default: + ui->pbShuffle->setIcon(QIcon(":/img/shuffle-off.png")); + ui->pbShuffle->setText("Shuffle Off"); + break; + } + switch(repeat) + { + case 0: + ui->pbRepeat->setIcon(QIcon(":/img/repeat-non.png")); + ui->pbRepeat->setText("Repeat Off"); + break; + case 1: + ui->pbRepeat->setIcon(QIcon(":/img/repeat-one.png")); + ui->pbRepeat->setText("Repeat One"); + break; + case 2: + ui->pbRepeat->setIcon(QIcon(":/img/repeat-all.png")); + ui->pbRepeat->setText("Repeat All"); + break; + } + delete plist; + } +} + +qmpPlistWindow::~qmpPlistWindow() +{ + delete ui; +} + +void qmpPlistWindow::showEvent(QShowEvent *event) +{ + if(qmpSettingsWindow::getSettingsIntf()->value("Behavior/DialogStatus","").toInt()) + { + qmpSettingsWindow::getSettingsIntf()->setValue("DialogStatus/PListWShown",1); + } + event->accept(); +} + +void qmpPlistWindow::closeEvent(QCloseEvent *event) +{ + setVisible(false); + if(!qmpMainWindow::getInstance()->isFinalizing()&&qmpSettingsWindow::getSettingsIntf()->value("Behavior/DialogStatus","").toInt()) + { + qmpSettingsWindow::getSettingsIntf()->setValue("DialogStatus/PListWShown",0); + } + if(qmpMainWindow::getInstance()->isFinalizing()&&qmpSettingsWindow::getSettingsIntf()->value("Behavior/RestorePlaylist","").toInt()) + { + QSettings* plist=new QSettings(QDir::homePath()+QString("/.config/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/Repeat",repeat); + plist->setValue("Playlist/Shuffle",shuffle); + plist->sync(); + delete plist; + } + emit dialogClosing(); + event->accept(); +} + +void qmpPlistWindow::moveEvent(QMoveEvent *event) +{ + if(qmpSettingsWindow::getSettingsIntf()->value("Behavior/DialogStatus","").toInt()) + { + qmpSettingsWindow::getSettingsIntf()->setValue("DialogStatus/PListW",event->pos()); + } +} + +void qmpPlistWindow::dropEvent(QDropEvent *event) +{ + QList l=event->mimeData()->urls(); + QStringList sl; + for(int i=0;imimeData()->hasFormat("application/x-midi")) + event->acceptProposedAction(); +} + +void qmpPlistWindow::emptyList() +{ + ui->lwFiles->clear(); +} +void qmpPlistWindow::insertItem(QString i) +{ + ui->lwFiles->addItem(new QListWidgetItem(i)); +} +void qmpPlistWindow::insertItems(QStringList il) +{ + ui->lwFiles->addItems(il); +} + +void 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)"); + else + sl=QFileDialog::getOpenFileNames(this,"Add File","","Midi files (*.mid *.midi)"); + if(sl.empty())return; + for(int i=0;ilwFiles->addItem(new QListWidgetItem(sl.at(i))); + } + if(qmpSettingsWindow::getSettingsIntf()->value("Behavior/DialogStatus","").toInt()) + qmpSettingsWindow::getSettingsIntf()->setValue("DialogStatus/FileDialogPath", + QUrl(sl.at(0)).toString(QUrl::RemoveFilename)); +} + +void qmpPlistWindow::on_pbAddFolder_clicked() +{ + QDirIterator di(QFileDialog::getExistingDirectory(this,"Add Folder")); + while(di.hasNext()) + { + QString c=di.next(); + if((c.endsWith(".mid")||c.endsWith(".midi"))&&fluid_is_midifile(c.toStdString().c_str())) + ui->lwFiles->addItem(new QListWidgetItem(c)); + } +} + +void qmpPlistWindow::on_pbRemove_clicked() +{ + QList sl=ui->lwFiles->selectedItems(); + for(int i=0;ilwFiles->removeItemWidget(sl.at(i)); + delete sl.at(i); + } +} + +void qmpPlistWindow::on_pbClear_clicked() +{ + while(ui->lwFiles->count()>0) + { + QListWidgetItem *d=ui->lwFiles->item(0); + ui->lwFiles->removeItemWidget(d); + delete d; + } +} + +void qmpPlistWindow::on_pbRepeat_clicked() +{ + ++repeat;repeat%=3; + switch(repeat) + { + case 0: + ui->pbRepeat->setIcon(QIcon(":/img/repeat-non.png")); + ui->pbRepeat->setText("Repeat Off"); + break; + case 1: + ui->pbRepeat->setIcon(QIcon(":/img/repeat-one.png")); + ui->pbRepeat->setText("Repeat One"); + break; + case 2: + ui->pbRepeat->setIcon(QIcon(":/img/repeat-all.png")); + ui->pbRepeat->setText("Repeat All"); + break; + } +} + +void qmpPlistWindow::on_pbShuffle_clicked() +{ + shuffle=1-shuffle; + switch(shuffle) + { + case 1: + ui->pbShuffle->setIcon(QIcon(":/img/shuffle.png")); + ui->pbShuffle->setText("Shuffle On"); + break; + case 0: + default: + ui->pbShuffle->setIcon(QIcon(":/img/shuffle-off.png")); + ui->pbShuffle->setText("Shuffle Off"); + break; + } +} + +QString qmpPlistWindow::getFirstItem() +{ + if(ui->lwFiles->count()==0)return QString(); + int id=0; + if(shuffle)id=rand()%ui->lwFiles->count(); + ui->lwFiles->setCurrentRow(id); + return ui->lwFiles->item(id)->text(); +} +QString qmpPlistWindow::getNextItem() +{ + if(ui->lwFiles->count()==0)return QString(); + if(repeat==1)return ui->lwFiles->item(ui->lwFiles->currentRow())->text(); + int id=ui->lwFiles->currentRow();++id;id%=ui->lwFiles->count(); + if(shuffle)id=rand()%ui->lwFiles->count(); + ui->lwFiles->setCurrentRow(id); + return ui->lwFiles->item(id)->text(); +} +QString qmpPlistWindow::getPrevItem() +{ + if(ui->lwFiles->count()==0)return QString(); + if(repeat==1)return ui->lwFiles->item(ui->lwFiles->currentRow())->text(); + int id=ui->lwFiles->currentRow();--id; + id<0?id+=ui->lwFiles->count():0; + if(shuffle)id=rand()%ui->lwFiles->count(); + ui->lwFiles->setCurrentRow(id); + return ui->lwFiles->item(id)->text(); +} +QString qmpPlistWindow::getSelectedItem() +{ + if(ui->lwFiles->count()==0)return QString(); + return ui->lwFiles->item(ui->lwFiles->currentRow())->text(); +} +int qmpPlistWindow::getRepeat(){return repeat;} + +void qmpPlistWindow::on_lwFiles_itemDoubleClicked() +{ + emit selectionChanging(); +} + +void qmpPlistWindow::on_pbSave_clicked() +{ + QSettings* plist=new QSettings(QFileDialog::getSaveFileName(this,"Save playlist",""), + 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/Repeat",repeat); + plist->setValue("Playlist/Shuffle",shuffle); + plist->sync(); + delete plist; +} + +void qmpPlistWindow::on_pbLoad_clicked() +{ + QSettings* plist=new QSettings(QFileDialog::getOpenFileName(this,"Load playlist",""), + QSettings::IniFormat); + int fc=plist->value("Playlist/FileCount",0).toInt(); + if(!fc)return; + ui->lwFiles->clear();for(int i=1;i<=fc;++i) + ui->lwFiles->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(); + switch(shuffle) + { + case 1: + ui->pbShuffle->setIcon(QIcon(":/img/shuffle.png")); + ui->pbShuffle->setText("Shuffle On"); + break; + case 0: + default: + ui->pbShuffle->setIcon(QIcon(":/img/shuffle-off.png")); + ui->pbShuffle->setText("Shuffle Off"); + break; + } + switch(repeat) + { + case 0: + ui->pbRepeat->setIcon(QIcon(":/img/repeat-non.png")); + ui->pbRepeat->setText("Repeat Off"); + break; + case 1: + ui->pbRepeat->setIcon(QIcon(":/img/repeat-one.png")); + ui->pbRepeat->setText("Repeat One"); + break; + case 2: + ui->pbRepeat->setIcon(QIcon(":/img/repeat-all.png")); + ui->pbRepeat->setText("Repeat All"); + break; + } + delete plist; +} diff --git a/qmidiplayer.src.d/qmpplistwindow.hpp b/qmidiplayer.src.d/qmpplistwindow.hpp new file mode 100644 index 0000000..6ceeb60 --- /dev/null +++ b/qmidiplayer.src.d/qmpplistwindow.hpp @@ -0,0 +1,57 @@ +#ifndef QMPPLISTWINDOW_H +#define QMPPLISTWINDOW_H + +#include +#include +#include +#include +#include +#include +#include + +namespace Ui { + class qmpPlistWindow; +} + +class qmpPlistWindow : public QDialog +{ + Q_OBJECT + + public: + explicit qmpPlistWindow(QWidget *parent=0); + ~qmpPlistWindow(); + void showEvent(QShowEvent *event); + void closeEvent(QCloseEvent *event); + void moveEvent(QMoveEvent *event); + void dropEvent(QDropEvent *event); + void dragEnterEvent(QDragEnterEvent *event); + int getRepeat(); + QString getFirstItem(); + QString getNextItem(); + QString getPrevItem(); + QString getSelectedItem(); + void emptyList(); + void insertItem(QString i); + void insertItems(QStringList il); + signals: + void dialogClosing(); + void selectionChanging(); + + public slots: + void on_pbAdd_clicked(); + private slots: + void on_pbAddFolder_clicked(); + void on_pbRemove_clicked(); + void on_pbClear_clicked(); + void on_pbRepeat_clicked(); + void on_pbShuffle_clicked(); + void on_lwFiles_itemDoubleClicked(); + void on_pbSave_clicked(); + void on_pbLoad_clicked(); + + private: + Ui::qmpPlistWindow *ui; + int shuffle,repeat;//rep 0=off 1=one 2=all +}; + +#endif // QMPPLISTWINDOW_H diff --git a/qmidiplayer.src.d/qmpplistwindow.ui b/qmidiplayer.src.d/qmpplistwindow.ui new file mode 100644 index 0000000..99124df --- /dev/null +++ b/qmidiplayer.src.d/qmpplistwindow.ui @@ -0,0 +1,263 @@ + + + qmpPlistWindow + + + + 0 + 0 + 530 + 321 + + + + + 530 + 321 + + + + + 530 + 321 + + + + true + + + Playlist + + + + + 10 + 280 + 121 + 36 + + + + text-align:left + + + Add + + + + :/img/add.png:/img/add.png + + + + 32 + 32 + + + + + + + 140 + 280 + 121 + 36 + + + + text-align:left + + + Add Folder + + + + :/img/addfolder.png:/img/addfolder.png + + + + 32 + 32 + + + + + + + 270 + 240 + 121 + 36 + + + + text-align:left + + + Repeat Off + + + + :/img/repeat-non.png:/img/repeat-non.png + + + + 32 + 32 + + + + + + + 400 + 240 + 121 + 36 + + + + text-align:left + + + Shuffle Off + + + + :/img/shuffle-off.png:/img/shuffle-off.png + + + + 32 + 32 + + + + + + + 10 + 240 + 121 + 36 + + + + text-align:left + + + Save + + + + :/img/save.png:/img/save.png + + + + 32 + 32 + + + + + + + 140 + 240 + 121 + 36 + + + + text-align:left + + + Load + + + + :/img/load.png:/img/load.png + + + + 32 + 32 + + + + + + + 270 + 280 + 121 + 36 + + + + text-align:left + + + Remove + + + + :/img/remove.png:/img/remove.png + + + + 32 + 32 + + + + + + + 400 + 280 + 121 + 36 + + + + text-align:left + + + Clear + + + + :/img/clear.png:/img/clear.png + + + + 32 + 32 + + + + + + + 10 + 10 + 511 + 221 + + + + false + + + true + + + QAbstractItemView::InternalMove + + + + + + + + diff --git a/qmidiplayer.src.d/qmppresetselect.cpp b/qmidiplayer.src.d/qmppresetselect.cpp new file mode 100644 index 0000000..be589c5 --- /dev/null +++ b/qmidiplayer.src.d/qmppresetselect.cpp @@ -0,0 +1,99 @@ +#include +#include "qmppresetselect.hpp" +#include "ui_qmppresetselect.h" +#include "qmpmainwindow.hpp" + +qmpPresetSelector::qmpPresetSelector(QWidget *parent) : + QDialog(parent), + ui(new Ui::qmpPresetSelector) +{ + ui->setupUi(this); +} + +qmpPresetSelector::~qmpPresetSelector() +{ + delete ui; +} + +void qmpPresetSelector::showEvent(QShowEvent *e) +{ + memset(presets,0,sizeof(presets)); + CMidiPlayer *plyr=qmpMainWindow::getInstance()->getPlayer(); + if(!plyr->getSFCount())return e->ignore(); + int sfc=plyr->getSFCount(); + for(int i=sfc-1;i>=0;--i) + { + fluid_sfont_t* psf=plyr->getSFPtr(i); + fluid_preset_t preset; + psf->iteration_start(psf); + while(psf->iteration_next(psf,&preset)) + strcpy(presets[preset.get_banknum(&preset)][preset.get_num(&preset)],preset.get_name(&preset)); + } + 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->getSFCount())return; + ch=chid;int b=0,p=0,r;char name[64]; + sprintf(name,"Preset Selection - Channel #%d",ch+1); + setWindowTitle(name); + plyr->getChannelPreset(chid,&b,&p,name); + for(int i=0;ilwBankSelect->count();++i) + { + sscanf(ui->lwBankSelect->item(i)->text().toStdString().c_str(),"%d",&r); + if(r==b){ui->lwBankSelect->setCurrentRow(i);break;} + } + r=0; + ui->lwPresetSelect->clear(); + for(int i=0,cr=0;i<128;++i) + if(strlen(presets[b][i])) + { + sprintf(name,"%d %s",i,presets[b][i]); + if(i==p)r=cr; + ui->lwPresetSelect->addItem(name); + cr++; + } + ui->lwPresetSelect->setCurrentRow(r); +} + +void qmpPresetSelector::on_pbCancel_clicked() +{ + close(); +} + +void qmpPresetSelector::on_pbOk_clicked() +{ + CMidiPlayer *plyr=qmpMainWindow::getInstance()->getPlayer(); + int b,p;sscanf(ui->lwBankSelect->currentItem()->text().toStdString().c_str(),"%d",&b); + sscanf(ui->lwPresetSelect->currentItem()->text().toStdString().c_str(),"%d",&p); + plyr->setChannelPreset(ch,b,p); + close(); +} + +void qmpPresetSelector::on_lwPresetSelect_itemDoubleClicked() +{ + on_pbOk_clicked(); +} + +void qmpPresetSelector::on_lwBankSelect_currentRowChanged() +{ + ui->lwPresetSelect->clear(); + if(!ui->lwBankSelect->currentItem())return; + char name[30];int b; + sscanf(ui->lwBankSelect->currentItem()->text().toStdString().c_str(),"%d",&b); + for(int i=0;i<128;++i) + if(strlen(presets[b][i])) + { + sprintf(name,"%d %s",i,presets[b][i]); + ui->lwPresetSelect->addItem(name); + } +} diff --git a/qmidiplayer.src.d/qmppresetselect.hpp b/qmidiplayer.src.d/qmppresetselect.hpp new file mode 100644 index 0000000..54f5764 --- /dev/null +++ b/qmidiplayer.src.d/qmppresetselect.hpp @@ -0,0 +1,36 @@ +#ifndef QMPPRESETSELECT_H +#define QMPPRESETSELECT_H + +#include +#include + +namespace Ui { + class qmpPresetSelector; +} + +class qmpPresetSelector:public QDialog +{ + Q_OBJECT + + public: + explicit qmpPresetSelector(QWidget *parent = 0); + ~qmpPresetSelector(); + void showEvent(QShowEvent* e); + void setupWindow(int chid); + + private slots: + void on_pbCancel_clicked(); + + void on_pbOk_clicked(); + + void on_lwBankSelect_currentRowChanged(); + + void on_lwPresetSelect_itemDoubleClicked(); + + private: + Ui::qmpPresetSelector *ui; + char presets[129][128][24]; + int ch; +}; + +#endif // QMPPRESETSELECT_H diff --git a/qmidiplayer.src.d/qmppresetselect.ui b/qmidiplayer.src.d/qmppresetselect.ui new file mode 100644 index 0000000..f18600d --- /dev/null +++ b/qmidiplayer.src.d/qmppresetselect.ui @@ -0,0 +1,106 @@ + + + qmpPresetSelector + + + + 0 + 0 + 404 + 300 + + + + + 404 + 300 + + + + + 404 + 300 + + + + Preset Selection + + + true + + + + + 10 + 30 + 71 + 221 + + + + + + + 90 + 30 + 301 + 221 + + + + + + + 10 + 10 + 66 + 20 + + + + Bank + + + + + + 90 + 10 + 66 + 20 + + + + Preset + + + + + + 300 + 260 + 97 + 36 + + + + OK + + + + + + 190 + 260 + 97 + 36 + + + + Cancel + + + + + + diff --git a/qmidiplayer.src.d/qmpsettingswindow.cpp b/qmidiplayer.src.d/qmpsettingswindow.cpp new file mode 100644 index 0000000..c2e31a2 --- /dev/null +++ b/qmidiplayer.src.d/qmpsettingswindow.cpp @@ -0,0 +1,289 @@ +#include +#include +#include "qmpsettingswindow.hpp" +#include "ui_qmpsettingswindow.h" +#include "qmpmainwindow.hpp" + +QSettings *qmpSettingsWindow::settings=NULL; + +void qmpFluidForEachOpt(void* data,char* /*name*/,char* option) +{ + QComboBox *pcb=(QComboBox*)data; + pcb->addItem(option); +} + +qmpSettingsWindow::qmpSettingsWindow(QWidget *parent) : + QDialog(parent), + ui(new Ui::qmpSettingsWindow) +{ + ui->setupUi(this); + connect(this,SIGNAL(dialogClosing()),parent,SLOT(dialogClosed())); + settings=new QSettings(QDir::homePath()+QString("/.config/qmprc"),QSettings::IniFormat); + settingsInit(); +} + +qmpSettingsWindow::~qmpSettingsWindow() +{ + delete settings; + delete ui; +} + +void qmpSettingsWindow::closeEvent(QCloseEvent *event) +{ + setVisible(false); + settings->sync(); + emit dialogClosing(); + event->accept(); +} + +QListWidget* qmpSettingsWindow::getSFWidget(){return ui->lwSoundfont;} + +void qmpSettingsWindow::on_buttonBox_accepted() +{ + settingsUpdate(); + emit dialogClosing(); +} + +void qmpSettingsWindow::on_buttonBox_rejected() +{ + settingsInit(); + emit dialogClosing(); +} + +void qmpSettingsWindow::settingsInit() +{ + fluid_settings_t *fsettings=new_fluid_settings(); + + settings->setValue("Midi/DefaultOutput",settings->value("Midi/DefaultOutput","Internal FluidSynth")); + //this item is still a stub... + + 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 8192 +#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 + + selected=-1; + for(int i=0;icbBufCnt->count();++i) + if(ui->cbBufCnt->itemText(i).toInt()==settings->value("Audio/BufCnt",2).toInt()) + {selected=i;break;} + if(~selected)ui->cbBufCnt->setCurrentIndex(selected); + else if(settings->value("Audio/BufCnt",2).toInt()>=2&&settings->value("Audio/BufCnt",2).toInt()<=64) + ui->cbBufCnt->setCurrentText(settings->value("Audio/BufCnt",2).toString()); + else ui->cbBufCnt->setCurrentText("2"); + settings->setValue("Audio/BufCnt",ui->cbBufCnt->currentText().toInt()); + + 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","GS").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)); + + int sfc=settings->value("SoundFonts/SFCount",0).toInt(); + ui->lwSoundfont->clear();for(int i=1;i<=sfc;++i) + ui->lwSoundfont->addItem(settings->value("SoundFonts/SF"+QString::number(i),"").toString()); + settings->setValue("SoundFonts/SFCount",sfc); + + 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->sync(); + delete_fluid_settings(fsettings); +} + +void qmpSettingsWindow::settingsUpdate() +{ + settings->setValue("Midi/DefaultOutput",settings->value("Midi/DefaultOutput","Internal FluidSynth")); + //this item is still a stub... + + 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()); + + settings->setValue("SoundFonts/SFCount",ui->lwSoundfont->count()); + for(int i=0;ilwSoundfont->count();++i) + settings->setValue("SoundFonts/SF"+QString::number(i+1),ui->lwSoundfont->item(i)->text()); + + 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); + 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"); + } + + settings->setValue("Behavior/SingleInstance",ui->cbPersistentfs->isChecked()?1:0); + 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;ilwSoundfont->addItem(new QListWidgetItem(sl.at(i))); + } +} + +void qmpSettingsWindow::on_pbRemove_clicked() +{ + QList sl=ui->lwSoundfont->selectedItems(); + for(int i=0;ilwSoundfont->removeItemWidget(sl.at(i)); + delete sl.at(i); + } +} + +void qmpSettingsWindow::on_pbUp_clicked() +{ + int cid=ui->lwSoundfont->currentRow(); + QListWidgetItem *ci=ui->lwSoundfont->takeItem(cid); + ui->lwSoundfont->insertItem(cid-1,ci); + ui->lwSoundfont->setCurrentRow(cid-1); +} + +void qmpSettingsWindow::on_pbDown_clicked() +{ + int cid=ui->lwSoundfont->currentRow(); + QListWidgetItem *ci=ui->lwSoundfont->takeItem(cid); + ui->lwSoundfont->insertItem(cid+1,ci); + ui->lwSoundfont->setCurrentRow(cid+1); +} + +void qmpSettingsWindow::on_cbAutoBS_stateChanged() +{ + ui->lbBSMode->setText(ui->cbAutoBS->isChecked()?"Fallback bank select mode":"Bank select mode"); +} diff --git a/qmidiplayer.src.d/qmpsettingswindow.hpp b/qmidiplayer.src.d/qmpsettingswindow.hpp new file mode 100644 index 0000000..c506de4 --- /dev/null +++ b/qmidiplayer.src.d/qmpsettingswindow.hpp @@ -0,0 +1,47 @@ +#ifndef QMPSETTINGSWINDOW_H +#define QMPSETTINGSWINDOW_H + +#include +#include +#include +#include + +namespace Ui { + class qmpSettingsWindow; +} + +class qmpSettingsWindow:public QDialog +{ + Q_OBJECT + + public: + explicit qmpSettingsWindow(QWidget *parent=0); + ~qmpSettingsWindow(); + void closeEvent(QCloseEvent *event); + void settingsInit(); + QListWidget* getSFWidget(); + signals: + void dialogClosing(); + + private slots: + 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(); + + private: + Ui::qmpSettingsWindow *ui; + void settingsUpdate(); + static QSettings *settings; + public: static QSettings* getSettingsIntf(){return settings;} +}; + +#endif // QMPSETTINGSWINDOW_H diff --git a/qmidiplayer.src.d/qmpsettingswindow.ui b/qmidiplayer.src.d/qmpsettingswindow.ui new file mode 100644 index 0000000..330afa2 --- /dev/null +++ b/qmidiplayer.src.d/qmpsettingswindow.ui @@ -0,0 +1,761 @@ + + + qmpSettingsWindow + + + + 0 + 0 + 494 + 445 + + + + + 494 + 445 + + + + Settings + + + + + + 0 + + + + Midi + + + + + + + + + 0 + 0 + + + + Default Output Device + + + + + + + + 0 + 0 + + + + + Internal FluidSynth + + + + + + + + + + + 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 + + + + + + + + + + + Synth + + + + + + Audio Buffer Count + + + + + + + Audio Buffer Size + + + + + + + true + + + 1 + + + + 64 + + + + + 128 + + + + + 256 + + + + + 512 + + + + + 1024 + + + + + 2048 + + + + + 4096 + + + + + 8192 + + + + + + + + Audio Frequency + + + + + + + true + + + + 2 + + + + + 4 + + + + + 8 + + + + + 16 + + + + + 32 + + + + + 64 + + + + + + + + Audio Driver + + + + + + + + 16bits + + + + + float + + + + + + + + + + + 2 + + + + 22050 + + + + + 44100 + + + + + 48000 + + + + + 96000 + + + + + + + + Audio 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 + + + + + + + + + + + + + :/img/add.png:/img/add.png + + + + 24 + 24 + + + + + + + + + + + + :/img/remove.png:/img/remove.png + + + + 24 + 24 + + + + + + + + + + + + :/img/up.png:/img/up.png + + + + 24 + 24 + + + + + + + + + + + + :/img/down.png:/img/down.png + + + + 24 + 24 + + + + + + + + + + + Behavior + + + + + + Restore last playlist on startup + + + + + + + Load files in the same folder + + + + + + + Save dialog status + + + + + + + Save parameters in effects window + + + + + + + Persistent fluidsynth instance + + + + + + + + + Visualization Mode + + + + + + + + + + + + + + View distance + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 50 + 20 + + + + + + + + + 60 + 0 + + + + Qt::Horizontal + + + + + + + + + + + + + + Note stretch + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 60 + 20 + + + + + + + + + 60 + 0 + + + + Qt::Horizontal + + + + + + + + + + + + + + Fog Start + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 82 + 20 + + + + + + + + + 60 + 0 + + + + Qt::Horizontal + + + + + + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + + + buttonBox + accepted() + qmpSettingsWindow + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + qmpSettingsWindow + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/qmidiplayer.src.d/resources.qrc b/qmidiplayer.src.d/resources.qrc new file mode 100644 index 0000000..351d2fa --- /dev/null +++ b/qmidiplayer.src.d/resources.qrc @@ -0,0 +1,36 @@ + + + ../img/add.png + ../img/list.png + ../img/addfolder.png + ../img/channel.png + ../img/prev.png + ../img/qmidiplyr.png + ../img/remove.png + ../img/clear.png + ../img/down.png + ../img/effects.png + ../img/repeat-all.png + ../img/repeat-base.png + ../img/repeat-non.png + ../img/load.png + ../img/next.png + ../img/repeat-one.png + ../img/save.png + ../img/settings.png + ../img/pause.png + ../img/play.png + ../img/shuffle-off.png + ../img/shuffle.png + ../img/stop.png + ../img/up.png + ../img/visualization.png + ../img/mainw.png + ../img/chanw.png + ../doc/index.html + ../doc/version.html + ../doc/license.html + ../doc/mainwindow.html + ../doc/channeldialog.html + + diff --git a/qmidiplayerlite.pro b/qmidiplayerlite.pro new file mode 100644 index 0000000..be7679d --- /dev/null +++ b/qmidiplayerlite.pro @@ -0,0 +1,24 @@ +TEMPLATE = app + +QT += qml quick +unix:QT += widgets +win32:QT += widgets +CONFIG += c++11 + +SOURCES += ./qmidiplayerlite.src.d/main.cpp \ + ./common/qmpmidiplay.cpp \ + ./common/qmpmidiread.cpp + +RESOURCES += ./qmidiplayerlite.src.d/qml.qrc + +# Additional import path used to resolve QML modules in Qt Creator's code model +QML_IMPORT_PATH = + +# Default rules for deployment. +include(./qmidiplayerlite.src.d/deployment.pri) + +HEADERS += \ + ./common/qmpmidiplay.hpp \ + ./qmidiplayerlite.src.d/qmpcorewrapper.hpp + +LIBS += -lfluidsynth diff --git a/qmidiplayerlite.src.d/deployment.pri b/qmidiplayerlite.src.d/deployment.pri new file mode 100644 index 0000000..265ce71 --- /dev/null +++ b/qmidiplayerlite.src.d/deployment.pri @@ -0,0 +1,13 @@ +unix:!android { + isEmpty(target.path) { + qnx { + target.path = /tmp/$${TARGET}/bin + } else { + target.path = /opt/$${TARGET}/bin + } + export(target.path) + } + INSTALLS += target +} + +export(INSTALLS) diff --git a/qmidiplayerlite.src.d/main.cpp b/qmidiplayerlite.src.d/main.cpp new file mode 100644 index 0000000..1a87b33 --- /dev/null +++ b/qmidiplayerlite.src.d/main.cpp @@ -0,0 +1,15 @@ +#include +#include +#include +#include "qmpcorewrapper.hpp" + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + qmlRegisterType("org.chrisoft.qmpcore",1,0,"CQMPCoreWrapper"); + + QQmlApplicationEngine engine; + engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); + + return app.exec(); +} diff --git a/qmidiplayerlite.src.d/main.qml b/qmidiplayerlite.src.d/main.qml new file mode 100644 index 0000000..0ec0975 --- /dev/null +++ b/qmidiplayerlite.src.d/main.qml @@ -0,0 +1,144 @@ +import QtQuick 2.3 +import QtQuick.Window 2.2 +import QtQuick.Controls 1.0 +import QtQuick.Dialogs 1.0 +import org.chrisoft.qmpcore 1.0 + +Window { + id: window1 + width: 420 + height: 240 + title: "QMidiPlayer Lite" + visible: true + property bool playing + playing: false + + MouseArea { + id: mouseArea1 + anchors.rightMargin: 0 + anchors.bottomMargin: 0 + anchors.leftMargin: 0 + anchors.topMargin: 0 + anchors.fill: parent + onClicked: { + //Qt.quit(); + } + + Button { + id: button2 + x: 170 + text: qsTr("Play") + anchors.top: parent.top + anchors.topMargin: 172 + anchors.horizontalCenter: parent.horizontalCenter + onClicked: { + if(!playing) + { + qmpcore.loadFile(fileName.text); + qmpcore.initFluidSynth(); + qmpcore.playFile(); + playing=true; + uiTimer.start(); + text="Stop"; + } + else + { + qmpcore.stop(); + playing=false; + text="Play"; + hsTimer.value=0;uiTimer.stop(); + } + } + } + + Slider { + id: hsTimer + y: 210 + height: 22 + anchors.right: parent.right + anchors.rightMargin: 8 + anchors.left: parent.left + anchors.leftMargin: 8 + anchors.bottom: parent.bottom + anchors.bottomMargin: 8 + tickmarksEnabled: false + stepSize: 1 + maximumValue: 100 + property bool autovalchange: false + onValueChanged: { + if(autovalchange||pressed)return; + if(playing){qmpcore.setTCeptr(value);qmpcore.panic();} + } + onPressedChanged: { + if(!pressed) + { + /*if(playing) + { + if(ui->hsTimer->value()==100){on_pbNext_clicked();return;} + player->setTCeptr(player->getStamp(ui->hsTimer->value()),ui->hsTimer->value()); + player->playerPanic(); + offset=ui->hsTimer->value()/100.*player->getFtime(); + st=std::chrono::steady_clock::now(); + } + else + { + player->setTCeptr(player->getStamp(ui->hsTimer->value()),ui->hsTimer->value()); + offset=ui->hsTimer->value()/100.*player->getFtime(); + char ts[100]; + sprintf(ts,"%02d:%02d",(int)(offset)/60,(int)(offset)%60); + ui->lbCurTime->setText(ts); + }*/ + if(playing){qmpcore.setTCeptr(value);qmpcore.panic();} + } + } + } + } + + CQMPCoreWrapper { + id: qmpcore + } + Timer { + id: uiTimer + interval: 100 + running: false + repeat: true + onTriggered: { + if(!hsTimer.pressed) + { + hsTimer.autovalchange=true; + hsTimer.value=qmpcore.getProgress(); + hsTimer.autovalchange=false; + } + } + } + + Text { + id: fileName + text: qsTr("...") + anchors.centerIn: parent + } + + Button { + id: button1 + x: 170 + width: 80 + height: 27 + text: qsTr("Open") + anchors.top: parent.top + anchors.topMargin: 142 + anchors.horizontalCenter: parent.horizontalCenter + onClicked: { + fileDialog.open(); + } + } + + FileDialog { + id: fileDialog + title: qsTr("Select midi file") + nameFilters: ["MIDI Files (*.mid *.midi)"] + onAccepted: { + fileName.text=fileUrl; + } + } +} + diff --git a/qmidiplayerlite.src.d/qml.qrc b/qmidiplayerlite.src.d/qml.qrc new file mode 100644 index 0000000..5f6483a --- /dev/null +++ b/qmidiplayerlite.src.d/qml.qrc @@ -0,0 +1,5 @@ + + + main.qml + + diff --git a/qmidiplayerlite.src.d/qmpcorewrapper.hpp b/qmidiplayerlite.src.d/qmpcorewrapper.hpp new file mode 100644 index 0000000..558ed74 --- /dev/null +++ b/qmidiplayerlite.src.d/qmpcorewrapper.hpp @@ -0,0 +1,58 @@ +#ifndef QMPCOREWRAPPER_H +#define QMPCOREWRAPPER_H +#include +#include +#include +#include +#include "../common/qmpmidiplay.hpp" +class CQMPCoreWrapper:public QObject +{ + Q_OBJECT +private: + CMidiPlayer *mp; + std::thread *playerTh; + int curprog; +public: + explicit CQMPCoreWrapper(QObject* parent=0):QObject(parent) + { + mp=new CMidiPlayer(false); + } + ~CQMPCoreWrapper(){delete mp;} + Q_INVOKABLE void initFluidSynth() + { + fluid_settings_t *fsettings=mp->getFluidSettings(); + fluid_settings_setstr(fsettings,"audio.driver","pulseaudio"); + mp->fluidInitialize(); + mp->pushSoundFont("/media/Files/FluidR3_Ext.sf2"); + } + Q_INVOKABLE void deinitFluidSynth() + { + mp->fluidDeinitialize(); + } + Q_INVOKABLE void loadFile(QUrl file) + { + mp->playerLoadFile(file.toLocalFile().toStdString().c_str()); + mp->playerInit();curprog=0; + } + Q_INVOKABLE void playFile() + { + playerTh=new std::thread(&CMidiPlayer::playerThread,mp); + } + Q_INVOKABLE void stop() + { + mp->playerDeinit();playerTh->join();delete playerTh; + } + Q_INVOKABLE int getProgress() + { + while(!mp->isFinished()&&mp->getTCeptr()>mp->getStamp(curprog) + &&curprog<=100) + ++curprog; + return curprog; + } + Q_INVOKABLE void panic(){mp->playerPanic();} + Q_INVOKABLE void setTCeptr(int perct) + { + mp->setTCeptr(mp->getStamp(perct),perct);curprog=perct; + } +}; +#endif // QMPCOREWRAPPER_H diff --git a/qmidiplayerlite.src.d/qmpmidiplay.cpp b/qmidiplayerlite.src.d/qmpmidiplay.cpp new file mode 100644 index 0000000..baec9a2 --- /dev/null +++ b/qmidiplayerlite.src.d/qmpmidiplay.cpp @@ -0,0 +1,406 @@ +#include +#include +#include +#include +#include "qmpmidiplay.hpp" +#ifdef _WIN32 +#include +uint64_t pf; +#endif +void CMidiPlayer::fluidPreInitialize() +{ + settings=new_fluid_settings(); +} +void CMidiPlayer::fluidInitialize() +{ + synth=new_fluid_synth(settings); + adriver=new_fluid_audio_driver(settings,synth); + fluid_synth_set_chorus(synth,FLUID_CHORUS_DEFAULT_N,FLUID_CHORUS_DEFAULT_LEVEL, + FLUID_CHORUS_DEFAULT_SPEED,FLUID_CHORUS_DEFAULT_DEPTH, + FLUID_CHORUS_DEFAULT_TYPE); +#ifndef _WIN32 + if(!singleInstance) + { + if(midiFile->getStandard()==4) + fluid_synth_set_channel_type(synth,9,CHANNEL_TYPE_MELODIC); + else if(midiFile->getStandard()==1) + fluid_synth_set_channel_type(synth,9,CHANNEL_TYPE_DRUM); + else + { + fluid_synth_set_channel_type(synth,9,CHANNEL_TYPE_DRUM); + fluid_synth_bank_select(synth,9,128); + } + } +#endif +} +void CMidiPlayer::fluidDeinitialize() +{ + if(!synth||!adriver||!settings)return; + delete_fluid_settings(settings); + delete_fluid_audio_driver(adriver); + delete_fluid_synth(synth); + settings=NULL;synth=NULL;adriver=NULL; +} +void CMidiPlayer::processEvent(const SEvent *e) +{ + switch(e->type&0xF0) + { + case 0x80://Note off + fluid_synth_noteoff(synth,e->type&0x0F,e->p1); + break; + case 0x90://Note on + if((mute>>(e->type&0x0F))&1)break;//muted + if(solo&&!((solo>>(e->type&0x0F))&1))break; + fluid_synth_noteon(synth,e->type&0x0F,e->p1,e->p2); + break; + case 0xB0://CC + if(e->p1==100)rpnid=e->p2; + if(e->p1==6)rpnval=e->p2; + if(~rpnid&&~rpnval) + { + if(rpnid==0)fluid_synth_pitch_wheel_sens(synth,e->type&0x0F,rpnval); + rpnid=rpnval=-1; + } + fluid_synth_cc(synth,e->type&0x0F,e->p1,e->p2); + break; + case 0xC0://PC + fluid_synth_program_change(synth,e->type&0x0F,e->p1); + break; + case 0xE0://PW + fluid_synth_pitch_bend(synth,e->type&0x0F,e->p1); + break; + case 0xF0://Meta/SysEx + if((e->type&0x0F)==0x0F) + { + switch(e->p1) + { + case 0x51: + ctempo=e->p2;dpt=ctempo*1000/divs; + break; + case 0x58: + ctsn=e->p2>>24; + ctsd=1<<((e->p2>>16)&0xFF); + break; + case 0x59: + cks=e->p2; + break; + case 0x01:case 0x02:case 0x03: + case 0x04:case 0x05:case 0x06: + case 0x07: + if(e->str)puts(e->str); + break; + } + } + if((e->type&0x0F)==0x00||(e->type&0x0F)==07) + { + int io=0; + if(sendSysEx)fluid_synth_sysex(synth,e->str,e->p1,NULL,&io,NULL,0); + } + break; + } +} +void CMidiPlayer::processEventStub(const SEvent *e) +{ + switch(e->type&0xF0) + { + case 0xB0://CC + if(e->p1==100)rpnid=e->p2; + if(e->p1==6)rpnval=e->p2; + if(~rpnid&&~rpnval) + { + if(rpnid==0)ccc[e->type&0x0F][134]=rpnval; + rpnid=rpnval=-1; + } + ccc[e->type&0x0F][e->p1]=e->p2; + break; + case 0xC0://PC + ccc[e->type&0x0F][128]=e->p1; + break; + case 0xD0://CP + ccc[e->type&0x0F][129]=e->p1; + break; + case 0xE0://PW + ccc[e->type&0x0F][130]=e->p1; + break; + case 0xF0://Meta/SysEx + if((e->type&0x0F)==0x0F) + { + switch(e->p1) + { + case 0x51: + ctempo=e->p2;dpt=ctempo*1000/divs; + ccc[0][131]=dpt; + break; + case 0x58: + ccc[0][132]=e->p2; + break; + case 0x59: + ccc[0][133]=e->p2; + break; + } + } + break; + } +} +#ifdef _WIN32 +void w32usleep(uint64_t t) +{ + uint64_t st=0,ct=0; + QueryPerformanceCounter((LARGE_INTEGER*)&st); + do{ + if(t>10000+(ct-st)*1000000/pf)Sleep((t-(ct-st)*1000000/pf)/2000); + else if(t>5000+(ct-st)*1000000/pf)Sleep(1); + else std::this_thread::yield(); + QueryPerformanceCounter((LARGE_INTEGER*)&ct); + }while((ct-st)*1000000getEvent(0)->time;tceptrgetEventCount();) + { + while(tcpaused)std::this_thread::sleep_for(std::chrono::milliseconds(100)); + while(!tcstop&&midiFile&&tceptrgetEventCount()&&ct==midiFile->getEvent(tceptr)->time) + processEvent(midiFile->getEvent(tceptr++)); + if(tcstop||!midiFile||tceptr>=midiFile->getEventCount())break; + if(resumed)resumed=false; + else +#ifdef _WIN32 + w32usleep((midiFile->getEvent(tceptr)->time-ct)*(dpt/1000)); +#else + std::this_thread::sleep_for(std::chrono::nanoseconds(midiFile->getEvent(tceptr)->time-ct)*dpt); +#endif + if(tcstop||!midiFile)break; + ct=midiFile->getEvent(tceptr)->time; + } + while(!tcstop&&synth&&(waitvoice&&fluid_synth_get_active_voice_count(synth)>0))std::this_thread::sleep_for(std::chrono::milliseconds(2)); + finished=1; +} +void CMidiPlayer::fileTimer1Pass() +{ + ftime=.0;ctempo=0x7A120;dpt=ctempo*1000/divs; + for(uint32_t eptr=0,ct=midiFile->getEvent(0)->time;eptrgetEventCount();) + { + while(eptrgetEventCount()&&ct==midiFile->getEvent(eptr)->time) + processEventStub(midiFile->getEvent(eptr++)); + if(eptr>=midiFile->getEventCount())break; + ftime+=(midiFile->getEvent(eptr)->time-ct)*dpt/1e9; + ct=midiFile->getEvent(eptr)->time; + } +} +void CMidiPlayer::fileTimer2Pass() +{ + double ctime=.0;uint32_t c=1;ctempo=0x7A120;dpt=ctempo*1000/divs; + memset(stamps,0,sizeof(stamps));memset(ccstamps,0,sizeof(ccstamps)); + memset(ccc,0,sizeof(ccc));rpnid=rpnval=-1;for(int i=0;i<16;++i) + { + ccc[i][7]=100;ccc[i][10]=64;ccc[i][11]=127; + 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; + ccc[0][131]=dpt;ccc[0][132]=0x04021808; + ccc[0][133]=0;ccc[0][134]=2; + }if(midiFile->getStandard()!=4)ccc[9][0]=128; + for(int i=0;i<16;++i)for(int j=0;j<135;++j) + ccstamps[0][i][j]=ccc[i][j]; + for(uint32_t eptr=0,ct=midiFile->getEvent(0)->time;eptrgetEventCount();) + { + while(eptrgetEventCount()&&ct==midiFile->getEvent(eptr)->time) + processEventStub(midiFile->getEvent(eptr++)); + if(eptr>=midiFile->getEventCount())break; + ctime+=(midiFile->getEvent(eptr)->time-ct)*dpt/1e9; + while(ctime>ftime*c/100.) + { + for(int i=0;i<16;++i)for(int j=0;j<135;++j) + ccstamps[c][i][j]=ccc[i][j]; + stamps[c++]=eptr; + if(c>100)break; + } + ct=midiFile->getEvent(eptr)->time; + } + while(c<101) + { + for(int i=0;i<16;++i)for(int j=0;j<135;++j) + ccstamps[c][i][j]=ccc[i][j]; + stamps[c++]=midiFile->getEventCount(); + } +} +CMidiPlayer::CMidiPlayer(bool singleInst) +{ + midiFile=NULL;resumed=false;singleInstance=singleInst; + settings=NULL;synth=NULL;adriver=NULL;waitvoice=true; +#ifdef _WIN32 + QueryPerformanceFrequency((LARGE_INTEGER*)&pf); + timeBeginPeriod(1); +#endif +} +CMidiPlayer::~CMidiPlayer() +{ + if(singleInstance)fluidDeinitialize(); +#ifdef _WIN32 + timeEndPeriod(1); +#endif +} +void CMidiPlayer::playerPanic(bool reset) +{ + if(reset)for(int i=0;i<16;++i) + { + fluid_synth_pitch_bend(synth,i,8192); + fluid_synth_cc(synth,i,7,100); + fluid_synth_cc(synth,i,10,64); + fluid_synth_cc(synth,i,11,127); + } + for(int i=0;i<16;++i)fluid_synth_all_notes_off(synth,i); +} +bool CMidiPlayer::playerLoadFile(const char* fn) +{ + midiFile=new CMidiFile(fn); + if(!midiFile->isValid())return false; + divs=midiFile->getDivision(); + fileTimer1Pass(); + fileTimer2Pass(); + return true; +} +void CMidiPlayer::playerInit() +{ + ctempo=0x7A120;ctsn=4;ctsd=4;cks=0;dpt=ctempo*1000/divs; + tceptr=0;tcstop=0;tcpaused=0;finished=0;mute=solo=0; + sendSysEx=true;rpnid=rpnval=-1; + if(!singleInstance)fluidPreInitialize(); +} +void CMidiPlayer::playerDeinit() +{ + tceptr=0;tcstop=1;tcpaused=0; + delete midiFile;midiFile=NULL; + if(!singleInstance)fluidDeinitialize(); +} +void CMidiPlayer::playerThread() +{ + playEvents(); +} + +void CMidiPlayer::rendererLoadFile(const char* ofn) +{ + settings=new_fluid_settings(); + fluid_settings_setstr(settings,"audio.file.name",ofn); +} +void CMidiPlayer::rendererInit(const char* fn) +{ + finished=0; + synth=new_fluid_synth(settings); + player=new_fluid_player(synth); + fluid_player_add(player,fn); +} +void CMidiPlayer::rendererThread() +{ + fluid_file_renderer_t* renderer=new_fluid_file_renderer(synth); + fluid_player_play(player); + while(fluid_player_get_status(player)==FLUID_PLAYER_PLAYING) + if(fluid_file_renderer_process_block(renderer)!=FLUID_OK)break; + delete_fluid_file_renderer(renderer); + finished=1; +} +void CMidiPlayer::rendererDeinit() +{ + delete_fluid_player(player); + delete_fluid_synth(synth); + delete_fluid_settings(settings); + player=NULL;synth=NULL;settings=NULL; +} + +void CMidiPlayer::sendSysX(bool send){sendSysEx=send;} +uint32_t CMidiPlayer::getStamp(int id){return stamps[id];} +uint32_t CMidiPlayer::getTCeptr(){return tceptr;} +void CMidiPlayer::setTCeptr(uint32_t ep,uint32_t st) +{ + resumed=true; + if(ep==midiFile->getEventCount())tcstop=1;else tceptr=ep; + for(int i=0;i<16;++i) + { + for(int j=0;j<120;++j)fluid_synth_cc(synth,i,j,ccstamps[st][i][j]); + fluid_synth_program_change(synth,i,ccstamps[st][i][128]); + //fluid_synth_pitch_bend(synth,i,ccstamps[st][i][130]); + dpt=ccstamps[st][0][131];ctempo=dpt*divs/1000; + ctsn=ccstamps[st][0][132]>>24;ctsd=1<<((ccstamps[st][0][132]>>16)&0xFF); + cks=ccstamps[st][0][133]; + } +} +double CMidiPlayer::getFtime(){return ftime;} +void CMidiPlayer::getCurrentTimeSignature(int *n,int *d){*n=ctsn;*d=ctsd;} +void CMidiPlayer::getCurrentKeySignature(int *ks){*ks=cks;} +uint32_t CMidiPlayer::getFileNoteCount(){return midiFile?midiFile->getNoteCount():0;} +uint32_t CMidiPlayer::getFileStandard(){return midiFile?midiFile->getStandard():0;} +const char* CMidiPlayer::getTitle(){return midiFile?midiFile->getTitle():"";} +const char* CMidiPlayer::getCopyright(){return midiFile?midiFile->getCopyright():"";} +double CMidiPlayer::getTempo(){return 60./(ctempo/1e6)/**ctsd/4.*/;} +uint32_t CMidiPlayer::getTCpaused(){return tcpaused;} +void CMidiPlayer::setTCpaused(uint32_t ps){tcpaused=ps;} +uint32_t CMidiPlayer::isFinished(){return finished;} +void CMidiPlayer::setResumed(){resumed=true;} +void CMidiPlayer::setWaitVoice(bool wv){waitvoice=wv;} +void CMidiPlayer::setGain(double gain){if(settings)fluid_settings_setnum(settings,"synth.gain",gain);} +int CMidiPlayer::getPolyphone(){return synth?fluid_synth_get_active_voice_count(synth):0;} +int CMidiPlayer::getMaxPolyphone(){return synth?fluid_synth_get_polyphony(synth):0;} +void CMidiPlayer::setMaxPolyphone(int p){if(synth)fluid_synth_set_polyphony(synth,p);} + +void CMidiPlayer::getChannelPreset(int ch,int *b,int *p,char *name) +{ + if(!synth)return(void)(b=0,p=0,strcpy(name,"")); + fluid_synth_channel_info_t info; + fluid_synth_get_channel_info(synth,ch,&info); + *b=info.bank;*p=info.program; + strcpy(name,info.name); +} +void CMidiPlayer::setChannelPreset(int ch,int b,int p) +{ + if(!synth)return; + fluid_synth_bank_select(synth,ch,b); + fluid_synth_program_change(synth,ch,p); +} +//16MSB..LSB1 +void CMidiPlayer::setBit(uint16_t &n, uint16_t bn, uint16_t b) +{n^=(-b^n)&(1< +#include +#include +#include +struct SEvent +{ + uint32_t iid,time,p1,p2; + uint8_t type; + char *str; + SEvent(){time=p1=p2=0;type=0;str=NULL;} + SEvent(uint32_t _iid,uint32_t _t,char _tp,uint32_t _p1,uint32_t _p2,const char* s=NULL) + { + iid=_iid;time=_t;type=_tp; + p1=_p1;p2=_p2; + if(s){str=new char[strlen(s)+2];strcpy(str,s);}else str=NULL; + } +}; +class CMidiFile +{ + private: + SEvent *eventList[10000000]; + char *title,*copyright; + uint32_t eventc,std;//standard 0=? 1=GM 2=GM2 3=GS 4=XG + uint32_t fmt,trk,divs; + FILE *f; + int byteread,valid; + uint32_t notes,curt,curid; + + void error(int fatal,const char* format,...); + uint32_t readSW(); + uint32_t readDW(); + uint32_t readVL(); + int eventReader(); + void trackChunkReader(); + void headerChunkReader(); + int chunkReader(int hdrXp); + public: + CMidiFile(const char* fn); + ~CMidiFile(); + const SEvent* getEvent(uint32_t id); + uint32_t getEventCount(); + uint32_t getDivision(); + uint32_t getNoteCount(); + uint32_t getStandard(); + const char* getTitle(); + const char* getCopyright(); + bool isValid(); +}; +class CMidiPlayer +{ + private: + CMidiFile *midiFile; + uint32_t stamps[101]; + uint32_t ccstamps[101][16][135],ccc[16][135]; + //0..127:cc 128:pc 129:cp 130:pb 131:tempo 132:ts 133:ks 134:pbr + int32_t rpnid,rpnval; + uint16_t mute,solo; + double ftime; + bool sendSysEx,singleInstance,waitvoice; + fluid_settings_t* settings; + fluid_synth_t* synth; + fluid_audio_driver_t* adriver; + fluid_player_t* player; + uint32_t ctempo,ctsn,ctsd,dpt,divs,cks; + //raw tempo, timesig num., timesig den., delay per tick, division, keysig + //thread control + uint32_t tceptr,tcpaused,tcstop; + uint32_t finished,resumed; + + void setBit(uint16_t &n,uint16_t bn,uint16_t b); + void processEvent(const SEvent *e); + void processEventStub(const SEvent *e); + void playEvents(); + void fileTimer1Pass(); + void fileTimer2Pass(); + public: + CMidiPlayer(bool singleInst=false); + ~CMidiPlayer(); + bool playerLoadFile(const char* fn); + void playerInit(); + void fluidPreInitialize(); + void fluidInitialize(); + void fluidDeinitialize(); + void playerDeinit(); + void playerThread(); + void playerPanic(bool reset=false); + + void rendererLoadFile(const char* ofn); + void rendererInit(const char *fn); + void rendererThread(); + void rendererDeinit(); + + //playing control methods + uint32_t getStamp(int id); + uint32_t getTCeptr(); + void setTCeptr(uint32_t ep,uint32_t st); + uint32_t getTCpaused(); + void setTCpaused(uint32_t ps); + uint32_t isFinished(); + void setResumed(); + void setWaitVoice(bool wv); + + double getFtime(); + void getCurrentTimeSignature(int *n,int *d); + void getCurrentKeySignature(int *ks); + uint32_t getFileNoteCount(); + uint32_t getFileStandard(); + double getTempo(); + const char* getTitle(); + const char* getCopyright(); + + void setGain(double gain); + void sendSysX(bool send); + int getPolyphone(); + int getMaxPolyphone(); + void setMaxPolyphone(int p); + + 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); + int getCC(int ch,int id); + void setCC(int ch,int id,int val); + void getReverbPara(double *r,double *d,double *w,double *l); + void setReverbPara(int e,double r,double d,double w,double l); + void getChorusPara(int *fb,double *l,double *r,double *d,int *type); + void setChorusPara(int e,int fb,double l,double r,double d,int type); + + fluid_settings_t* getFluidSettings(); + void pushSoundFont(const char* sf); + int getSFCount(); + fluid_sfont_t* getSFPtr(int sfid); +}; +#endif diff --git a/qmidiplayerlite.src.d/qmpmidiread.cpp b/qmidiplayerlite.src.d/qmpmidiread.cpp new file mode 100644 index 0000000..0bcf597 --- /dev/null +++ b/qmidiplayerlite.src.d/qmpmidiread.cpp @@ -0,0 +1,240 @@ +//CLI Midi file player based on libfluidsynth +//Midi file reading module +//Written by Chris Xiong, 2015 +#include +#include +#include +#include +#include +#include +#include "qmpmidiplay.hpp" +const char* GM1SysX={"\xF0\x7E\x7F\x09\x01\xF7"}; +const char* GM2SysX={"\xF0\x7E\x7F\x09\x03\xF7"}; +const char* GSSysEx={"\xF0\x41\x10\x42\x12\x40\x00\x7F\x00\x41\xF7"}; +const char* XGSysEx={"\xF0\x43\x10\x4C\x00\x00\x7E\x00\xF7"}; +bool cmp(SEvent *a,SEvent *b){return a->time-b->time?a->timetime:a->iidiid;} +void CMidiFile::error(int fatal,const char* format,...) +{ + va_list ap; + va_start(ap,format);vfprintf(stderr,format,ap);va_end(ap); + fprintf(stderr," at %#lx\n",ftell(f)); + if(fatal)throw 2; +} +uint32_t CMidiFile::readSW() +{ + byteread+=2; + uint32_t ret=0; + for(int i=0;i<2;++i){ret<<=8;ret|=((uint32_t)fgetc(f))&0xFF;} + return ret; +} +uint32_t CMidiFile::readDW() +{ + byteread+=4; + uint32_t ret=0; + for(int i=0;i<4;++i){ret<<=8;ret|=((uint32_t)fgetc(f))&0xFF;} + return ret; +} +uint32_t CMidiFile::readVL() +{ + uint32_t ret=0,t,c=0; + do + { + t=fgetc(f); + if(++c>4)error(1,"E: Variable length type overflow."); + ret<<=7;ret|=(t&0x7F); + }while(t&0x80); + byteread+=c; + return ret; +} +int CMidiFile::eventReader()//returns 0 if End of Track encountered +{ + uint32_t delta=readVL();curt+=delta; + char type=fgetc(f);++byteread;uint32_t p1,p2; + static char lasttype; +retry: + switch(type&0xF0) + { + case 0x80://Note Off + p1=fgetc(f);p2=fgetc(f);byteread+=2; + eventList[eventc++]=new SEvent(curid,curt,type,p1,p2); + break; + case 0x90://Note On + p1=fgetc(f);p2=fgetc(f);byteread+=2; + if(p2) + { + ++notes; + eventList[eventc++]=new SEvent(curid,curt,type,p1,p2); + } + else + eventList[eventc++]=new SEvent(curid,curt,(type&0x0F)|0x80,p1,p2); + break; + case 0xA0://Note Aftertouch + p1=fgetc(f);p2=fgetc(f);byteread+=2; + eventList[eventc++]=new SEvent(curid,curt,type,p1,p2); + break; + case 0xB0://Controller Change + p1=fgetc(f);p2=fgetc(f);byteread+=2; + eventList[eventc++]=new SEvent(curid,curt,type,p1,p2); + break; + case 0xC0://Patch Change + p1=fgetc(f);++byteread; + eventList[eventc++]=new SEvent(curid,curt,type,p1,0); + break; + case 0xD0://Channel Aftertouch + p1=fgetc(f);++byteread; + eventList[eventc++]=new SEvent(curid,curt,type,p1,0); + break; + case 0xE0://Pitch wheel + p1=fgetc(f);p2=fgetc(f);byteread+=2; + eventList[eventc++]=new SEvent(curid,curt,type,(p1|(p2<<7))&0x3FFF,0); + break; + case 0xF0: + if((type&0x0F)==0x0F)//Meta Event + { + char metatype=fgetc(f);++byteread; + switch(metatype) + { + case 0x00://Sequence Number + fgetc(f);fgetc(f);fgetc(f); + byteread+=3; + break; + case 0x20://Channel Prefix + fgetc(f);fgetc(f);byteread+=2; + break; + case 0x2F://End of Track + fgetc(f);++byteread; + return 0; + break; + case 0x51://Set Tempo + p1=readDW();p1&=0x00FFFFFF; + eventList[eventc++]=new SEvent(curid,curt,type,metatype,p1); + break; + case 0x54://SMTPE offset, not handled. + fgetc(f);fgetc(f);fgetc(f); + fgetc(f);fgetc(f);fgetc(f); + byteread+=6; + break; + case 0x58://Time signature + fgetc(f);++byteread; + p1=readDW(); + eventList[eventc++]=new SEvent(curid,curt,type,metatype,p1); + break; + case 0x59://Key signature + fgetc(f);++byteread; + p1=readSW(); + eventList[eventc++]=new SEvent(curid,curt,type,metatype,p1); + break; + case 0x01:case 0x02:case 0x03: + case 0x04:case 0x05:case 0x06: + case 0x07:case 0x7F:default://text-like meta + { + uint32_t len=readVL(),c;char* str=NULL; + if(len<=1024&&len>0)str=new char[len+8]; + for(c=0;c0)delete[] str; + } + } + } + else if((type&0x0F)==0x00||(type&0x0F)==0x07)//SysEx + { + uint32_t len=readVL(),c;char* str=NULL; + str=new char[len+8]; + if((type&0x0F)==0x00) + { + str[0]=0xF0;++len; + for(c=1;cchnklen) + { + error(1,"E: Read past end of track."); + }*/ +} +void CMidiFile::headerChunkReader() +{ + int chnklen=readDW();byteread=0; + if(chnklen<6)error(1,"E: Header chunk too short."); + if(chnklen>6)error(0,"W: Header chunk length longer than expected. Ignoring extra bytes."); + fmt=readSW();trk=readSW();divs=readSW(); + if(divs&0x8000)error(1,"E: SMTPE format is not supported."); + for(;byteread0;--chnklen)fgetc(f);return 0; + } + else return trackChunkReader(),1; +} +CMidiFile::CMidiFile(const char* fn) +{ + title=copyright=NULL;notes=eventc=0;std=0;valid=1; + try + { + if(!(f=fopen(fn,"rb")))throw (fprintf(stderr,"E: file %s doesn't exist!\n",fn),2); + chunkReader(1); + for(uint32_t i=0;i -#include "qmpchanneleditor.hpp" -#include "ui_qmpchanneleditor.h" -#include "qmpmainwindow.hpp" - -qmpChannelEditor::qmpChannelEditor(QWidget *parent) : - QDialog(parent), - ui(new Ui::qmpChannelEditor) -{ - ui->setupUi(this); - styl=new QDialSkulptureStyle(); - QList dials=findChildren(); - for(int i=0;isetStyle(styl); -} - -qmpChannelEditor::~qmpChannelEditor() -{ - delete styl; - delete ui; -} - -void qmpChannelEditor::setupWindow(int chid) -{ - char str[256];if(~chid)ch=chid; - sprintf(str,"Channel Parameter Editor - Channel #%d",ch+1); - setWindowTitle(str); - CMidiPlayer* player=qmpMainWindow::getInstance()->getPlayer(); - int b,p; - player->getChannelPreset(ch,&b,&p,str); - ui->lbPresetName->setText(str); - sprintf(str,"BK: %d",b);ui->lbBank->setText(str); - sprintf(str,"PC: %d",p);ui->lbPreset->setText(str); - ui->lbChannelNumber->setText(QString::number(ch+1)); -#define setupControl(ccid,lb,d,ccname)\ - b=player->getCC(ch,ccid);\ - sprintf(str,"%s %d",ccname,b);\ - ui->lb->setText(str);\ - ui->d->setValue(b); - setupControl(7,lbVol,dVol,"Vol."); - setupControl(91,lbReverb,dReverb,"Rev."); - setupControl(93,lbChorus,dChorus,"Chr."); - setupControl(71,lbReso,dReso,"Res."); - setupControl(74,lbCut,dCut,"Cut."); - setupControl(73,lbAttack,dAttack,"Atk."); - setupControl(75,lbDecay,dDecay,"Dec."); - setupControl(72,lbRelease,dRelease,"Rel."); - setupControl(76,lbRate,dRate,"Rate"); - setupControl(77,lbDepth,dDepth,"Dep."); - setupControl(78,lbDelay,dDelay,"Del."); - b=player->getCC(ch,10); - if(b==64)strcpy(str,"Pan. C"); - else if(b<64)sprintf(str,"Pan. L%d",64-b);else sprintf(str,"Pan. R%d",b-64); - ui->lbPan->setText(str); - ui->dPan->setValue(b); -} - -void qmpChannelEditor::sendCC() -{ - CMidiPlayer* player=qmpMainWindow::getInstance()->getPlayer(); - player->setCC(ch,7,ui->dVol->value()); - player->setCC(ch,10,ui->dPan->value()); - player->setCC(ch,91,ui->dReverb->value()); - player->setCC(ch,93,ui->dChorus->value()); - player->setCC(ch,71,ui->dReso->value()); - player->setCC(ch,74,ui->dCut->value()); - player->setCC(ch,73,ui->dAttack->value()); - player->setCC(ch,75,ui->dDecay->value()); - player->setCC(ch,72,ui->dRelease->value()); - player->setCC(ch,76,ui->dRate->value()); - player->setCC(ch,77,ui->dDepth->value()); - player->setCC(ch,78,ui->dDelay->value()); -} - -void qmpChannelEditor::showEvent(QShowEvent *e) -{ - knobpressed=0; - setupWindow(); - connectSlots(); - connect(qmpMainWindow::getInstance()->getTimer(),SIGNAL(timeout()),this,SLOT(setupWindow())); - e->accept(); -} -void qmpChannelEditor::closeEvent(QCloseEvent *e) -{ - disconnectSlots(); - disconnect(qmpMainWindow::getInstance()->getTimer(),SIGNAL(timeout()),this,SLOT(setupWindow())); - e->accept(); -} - -void qmpChannelEditor::on_pbChLeft_clicked() -{ - disconnectSlots(); - if(ch>0)--ch;else ch=15;setupWindow(); - connectSlots(); -} - -void qmpChannelEditor::on_pbChRight_clicked() -{ - disconnectSlots(); - if(ch<15)++ch;else ch=0;setupWindow(); - connectSlots(); -} - -void qmpChannelEditor::commonPressed() -{disconnect(qmpMainWindow::getInstance()->getTimer(),SIGNAL(timeout()),this,SLOT(setupWindow()));knobpressed=1;} -void qmpChannelEditor::commonReleased() -{connect(qmpMainWindow::getInstance()->getTimer(),SIGNAL(timeout()),this,SLOT(setupWindow()));sendCC();knobpressed=0;} -void qmpChannelEditor::commonChanged() -{if(knobpressed){sendCC();setupWindow();}} - -void qmpChannelEditor::connectSlots() -{ - connect(ui->dCut,SIGNAL(sliderPressed()),this,SLOT(commonPressed())); - connect(ui->dReso,SIGNAL(sliderPressed()),this,SLOT(commonPressed())); - connect(ui->dReverb,SIGNAL(sliderPressed()),this,SLOT(commonPressed())); - connect(ui->dChorus,SIGNAL(sliderPressed()),this,SLOT(commonPressed())); - connect(ui->dVol,SIGNAL(sliderPressed()),this,SLOT(commonPressed())); - connect(ui->dPan,SIGNAL(sliderPressed()),this,SLOT(commonPressed())); - connect(ui->dAttack,SIGNAL(sliderPressed()),this,SLOT(commonPressed())); - connect(ui->dDecay,SIGNAL(sliderPressed()),this,SLOT(commonPressed())); - connect(ui->dRelease,SIGNAL(sliderPressed()),this,SLOT(commonPressed())); - connect(ui->dRate,SIGNAL(sliderPressed()),this,SLOT(commonPressed())); - connect(ui->dDepth,SIGNAL(sliderPressed()),this,SLOT(commonPressed())); - connect(ui->dDelay,SIGNAL(sliderPressed()),this,SLOT(commonPressed())); - - connect(ui->dCut,SIGNAL(sliderReleased()),this,SLOT(commonReleased())); - connect(ui->dReso,SIGNAL(sliderReleased()),this,SLOT(commonReleased())); - connect(ui->dReverb,SIGNAL(sliderReleased()),this,SLOT(commonReleased())); - connect(ui->dChorus,SIGNAL(sliderReleased()),this,SLOT(commonReleased())); - connect(ui->dVol,SIGNAL(sliderReleased()),this,SLOT(commonReleased())); - connect(ui->dPan,SIGNAL(sliderReleased()),this,SLOT(commonReleased())); - connect(ui->dAttack,SIGNAL(sliderReleased()),this,SLOT(commonReleased())); - connect(ui->dDecay,SIGNAL(sliderReleased()),this,SLOT(commonReleased())); - connect(ui->dRelease,SIGNAL(sliderReleased()),this,SLOT(commonReleased())); - connect(ui->dRate,SIGNAL(sliderReleased()),this,SLOT(commonReleased())); - connect(ui->dDepth,SIGNAL(sliderReleased()),this,SLOT(commonReleased())); - connect(ui->dDelay,SIGNAL(sliderReleased()),this,SLOT(commonReleased())); - - connect(ui->dCut,SIGNAL(valueChanged(int)),this,SLOT(commonChanged())); - connect(ui->dReso,SIGNAL(valueChanged(int)),this,SLOT(commonChanged())); - connect(ui->dReverb,SIGNAL(valueChanged(int)),this,SLOT(commonChanged())); - connect(ui->dChorus,SIGNAL(valueChanged(int)),this,SLOT(commonChanged())); - connect(ui->dVol,SIGNAL(valueChanged(int)),this,SLOT(commonChanged())); - connect(ui->dPan,SIGNAL(valueChanged(int)),this,SLOT(commonChanged())); - connect(ui->dAttack,SIGNAL(valueChanged(int)),this,SLOT(commonChanged())); - connect(ui->dDecay,SIGNAL(valueChanged(int)),this,SLOT(commonChanged())); - connect(ui->dRelease,SIGNAL(valueChanged(int)),this,SLOT(commonChanged())); - connect(ui->dRate,SIGNAL(valueChanged(int)),this,SLOT(commonChanged())); - connect(ui->dDepth,SIGNAL(valueChanged(int)),this,SLOT(commonChanged())); - connect(ui->dDelay,SIGNAL(valueChanged(int)),this,SLOT(commonChanged())); -} - -void qmpChannelEditor::disconnectSlots() -{ - disconnect(ui->dCut,SIGNAL(sliderPressed()),this,SLOT(commonPressed())); - disconnect(ui->dReso,SIGNAL(sliderPressed()),this,SLOT(commonPressed())); - disconnect(ui->dReverb,SIGNAL(sliderPressed()),this,SLOT(commonPressed())); - disconnect(ui->dChorus,SIGNAL(sliderPressed()),this,SLOT(commonPressed())); - disconnect(ui->dVol,SIGNAL(sliderPressed()),this,SLOT(commonPressed())); - disconnect(ui->dPan,SIGNAL(sliderPressed()),this,SLOT(commonPressed())); - disconnect(ui->dAttack,SIGNAL(sliderPressed()),this,SLOT(commonPressed())); - disconnect(ui->dDecay,SIGNAL(sliderPressed()),this,SLOT(commonPressed())); - disconnect(ui->dRelease,SIGNAL(sliderPressed()),this,SLOT(commonPressed())); - disconnect(ui->dRate,SIGNAL(sliderPressed()),this,SLOT(commonPressed())); - disconnect(ui->dDepth,SIGNAL(sliderPressed()),this,SLOT(commonPressed())); - disconnect(ui->dDelay,SIGNAL(sliderPressed()),this,SLOT(commonPressed())); - - disconnect(ui->dCut,SIGNAL(sliderReleased()),this,SLOT(commonReleased())); - disconnect(ui->dReso,SIGNAL(sliderReleased()),this,SLOT(commonReleased())); - disconnect(ui->dReverb,SIGNAL(sliderReleased()),this,SLOT(commonReleased())); - disconnect(ui->dChorus,SIGNAL(sliderReleased()),this,SLOT(commonReleased())); - disconnect(ui->dVol,SIGNAL(sliderReleased()),this,SLOT(commonReleased())); - disconnect(ui->dPan,SIGNAL(sliderReleased()),this,SLOT(commonReleased())); - disconnect(ui->dAttack,SIGNAL(sliderReleased()),this,SLOT(commonReleased())); - disconnect(ui->dDecay,SIGNAL(sliderReleased()),this,SLOT(commonReleased())); - disconnect(ui->dRelease,SIGNAL(sliderReleased()),this,SLOT(commonReleased())); - disconnect(ui->dRate,SIGNAL(sliderReleased()),this,SLOT(commonReleased())); - disconnect(ui->dDepth,SIGNAL(sliderReleased()),this,SLOT(commonReleased())); - disconnect(ui->dDelay,SIGNAL(sliderReleased()),this,SLOT(commonReleased())); - - disconnect(ui->dCut,SIGNAL(valueChanged(int)),this,SLOT(commonChanged())); - disconnect(ui->dReso,SIGNAL(valueChanged(int)),this,SLOT(commonChanged())); - disconnect(ui->dReverb,SIGNAL(valueChanged(int)),this,SLOT(commonChanged())); - disconnect(ui->dChorus,SIGNAL(valueChanged(int)),this,SLOT(commonChanged())); - disconnect(ui->dVol,SIGNAL(valueChanged(int)),this,SLOT(commonChanged())); - disconnect(ui->dPan,SIGNAL(valueChanged(int)),this,SLOT(commonChanged())); - disconnect(ui->dAttack,SIGNAL(valueChanged(int)),this,SLOT(commonChanged())); - disconnect(ui->dDecay,SIGNAL(valueChanged(int)),this,SLOT(commonChanged())); - disconnect(ui->dRelease,SIGNAL(valueChanged(int)),this,SLOT(commonChanged())); - disconnect(ui->dRate,SIGNAL(valueChanged(int)),this,SLOT(commonChanged())); - disconnect(ui->dDepth,SIGNAL(valueChanged(int)),this,SLOT(commonChanged())); - disconnect(ui->dDelay,SIGNAL(valueChanged(int)),this,SLOT(commonChanged())); -} diff --git a/qmpchanneleditor.hpp b/qmpchanneleditor.hpp deleted file mode 100644 index 0653af5..0000000 --- a/qmpchanneleditor.hpp +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef QMPCHANNELEDITOR_H -#define QMPCHANNELEDITOR_H - -#include -#include -#include -#include "qdialskulpturestyle.hpp" - -namespace Ui { - class qmpChannelEditor; -} - -class qmpChannelEditor:public QDialog -{ - Q_OBJECT - - public: - explicit qmpChannelEditor(QWidget *parent=0); - ~qmpChannelEditor(); - protected: - void showEvent(QShowEvent *e); - void closeEvent(QCloseEvent *e); - public slots: - void setupWindow(int chid=-1); - - private slots: - void commonPressed(); - void commonReleased(); - void commonChanged(); - void on_pbChLeft_clicked(); - void on_pbChRight_clicked(); - - private: - Ui::qmpChannelEditor *ui; - int ch,knobpressed; - void sendCC(); - void connectSlots(); - void disconnectSlots(); - QCommonStyle* styl; -}; - -#endif // QMPCHANNELEDITOR_H diff --git a/qmpchanneleditor.ui b/qmpchanneleditor.ui deleted file mode 100644 index 49e8c8e..0000000 --- a/qmpchanneleditor.ui +++ /dev/null @@ -1,602 +0,0 @@ - - - qmpChannelEditor - - - - 0 - 0 - 422 - 300 - - - - - 422 - 300 - - - - - 422 - 300 - - - - Dialog - - - - - 10 - 10 - 21 - 21 - - - - < - - - - - - 30 - 10 - 21 - 20 - - - - 1 - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - 50 - 10 - 21 - 21 - - - - > - - - - - - 90 - 10 - 261 - 51 - - - - - 16 - - - - Yamaha Grand Piano - - - - - - 10 - 30 - 81 - 20 - - - - BK: 0 - - - - - - 10 - 50 - 81 - 20 - - - - PC: 0 - - - - - - 0 - 70 - 141 - 101 - - - - Filters - - - - - 70 - 80 - 66 - 20 - - - - Res. 64 - - - Qt::AlignCenter - - - - - - 80 - 30 - 50 - 51 - - - - 127 - - - 64 - - - true - - - - - - 10 - 30 - 50 - 51 - - - - 127 - - - 64 - - - true - - - - - - 0 - 80 - 71 - 20 - - - - Cut. 64 - - - Qt::AlignCenter - - - - - - - 140 - 70 - 141 - 101 - - - - Effects - - - - - 70 - 80 - 66 - 20 - - - - Chr. 64 - - - Qt::AlignCenter - - - - - - 80 - 30 - 50 - 51 - - - - 127 - - - 64 - - - true - - - - - - 10 - 30 - 50 - 51 - - - - 127 - - - 64 - - - true - - - - - - 0 - 80 - 71 - 20 - - - - Rev. 64 - - - Qt::AlignCenter - - - - - - - 0 - 170 - 211 - 101 - - - - Envelope - - - - - 70 - 80 - 66 - 20 - - - - Dec. 64 - - - Qt::AlignCenter - - - - - - 80 - 30 - 50 - 51 - - - - 127 - - - 64 - - - true - - - - - - 10 - 30 - 50 - 51 - - - - 127 - - - 64 - - - true - - - - - - 0 - 80 - 71 - 20 - - - - Atk. 64 - - - Qt::AlignCenter - - - - - - 150 - 30 - 50 - 51 - - - - 127 - - - 64 - - - true - - - - - - 140 - 80 - 66 - 20 - - - - Rel. 64 - - - Qt::AlignCenter - - - - - - - 210 - 170 - 211 - 101 - - - - Vibrato - - - - - 70 - 80 - 66 - 20 - - - - Dep. 64 - - - Qt::AlignCenter - - - - - - 80 - 30 - 50 - 51 - - - - 127 - - - 64 - - - true - - - - - - 10 - 30 - 50 - 51 - - - - 127 - - - 64 - - - true - - - - - - 0 - 80 - 71 - 20 - - - - Rate 64 - - - Qt::AlignCenter - - - - - - 150 - 30 - 50 - 51 - - - - 127 - - - 64 - - - true - - - - - - 140 - 80 - 66 - 20 - - - - Del. 64 - - - Qt::AlignCenter - - - - - - - 280 - 70 - 141 - 101 - - - - Mixer - - - - - 70 - 80 - 66 - 20 - - - - Pan. C - - - Qt::AlignCenter - - - - - - 80 - 30 - 50 - 51 - - - - 127 - - - 64 - - - true - - - - - - 0 - 80 - 66 - 20 - - - - Vol. 127 - - - Qt::AlignCenter - - - - - - 10 - 30 - 50 - 51 - - - - 127 - - - 127 - - - true - - - - - - - diff --git a/qmpchannelswindow.cpp b/qmpchannelswindow.cpp deleted file mode 100644 index a9cf60e..0000000 --- a/qmpchannelswindow.cpp +++ /dev/null @@ -1,132 +0,0 @@ -#include -#include -#include -#include "qmpchannelswindow.hpp" -#include "ui_qmpchannelswindow.h" -#include "qmpmainwindow.hpp" - -qmpChannelsWindow::qmpChannelsWindow(QWidget *parent) : - QDialog(parent), - ui(new Ui::qmpChannelsWindow) -{ - ui->setupUi(this); - pselectw=new qmpPresetSelector(this); - ceditw=new qmpChannelEditor(this); - connect(this,SIGNAL(dialogClosing()),parent,SLOT(dialogClosed())); - for(int i=0;i<16;++i) - { - ui->twChannels->setCellWidget(i,0,new QCheckBox("")); - connect(ui->twChannels->cellWidget(i,0),SIGNAL(stateChanged(int)),this,SLOT(channelMSChanged())); - ui->twChannels->setCellWidget(i,1,new QCheckBox("")); - connect(ui->twChannels->cellWidget(i,1),SIGNAL(stateChanged(int)),this,SLOT(channelMSChanged())); - ui->twChannels->setCellWidget(i,2,new QComboBox()); - QComboBox *cb=(QComboBox*)ui->twChannels->cellWidget(i,2); - //stub - cb->addItem("Internal FluidSynth"); - ui->twChannels->setCellWidget(i,3,new QDCLabel("")); - ((QDCLabel*)ui->twChannels->cellWidget(i,3))->setID(i); - connect(ui->twChannels->cellWidget(i,3),SIGNAL(onDoubleClick(int)),this,SLOT(showPresetWindow(int))); - ui->twChannels->setCellWidget(i,4,new QDCPushButton("...")); - ((QDCLabel*)ui->twChannels->cellWidget(i,4))->setID(i); - connect(ui->twChannels->cellWidget(i,4),SIGNAL(onClick(int)),this,SLOT(showChannelEditorWindow(int))); - } - ui->twChannels->setColumnWidth(0,32); - ui->twChannels->setColumnWidth(1,32); - ui->twChannels->setColumnWidth(2,192); - ui->twChannels->setColumnWidth(3,192); - ui->twChannels->setColumnWidth(4,32); -} - -void qmpChannelsWindow::showEvent(QShowEvent *event) -{ - if(qmpSettingsWindow::getSettingsIntf()->value("Behavior/DialogStatus","").toInt()) - { - qmpSettingsWindow::getSettingsIntf()->setValue("DialogStatus/ChnlWShown",1); - } - event->accept(); -} - -void qmpChannelsWindow::closeEvent(QCloseEvent *event) -{ - setVisible(false); - if(!qmpMainWindow::getInstance()->isFinalizing()&&qmpSettingsWindow::getSettingsIntf()->value("Behavior/DialogStatus","").toInt()) - { - qmpSettingsWindow::getSettingsIntf()->setValue("DialogStatus/ChnlWShown",0); - } - emit dialogClosing(); - event->accept(); -} - -void qmpChannelsWindow::moveEvent(QMoveEvent *event) -{ - if(qmpSettingsWindow::getSettingsIntf()->value("Behavior/DialogStatus","").toInt()) - { - qmpSettingsWindow::getSettingsIntf()->setValue("DialogStatus/ChnlW",event->pos()); - } -} - -void qmpChannelsWindow::channelWindowsUpdate() -{ - if(qmpMainWindow::getInstance()->getPlayer()->isFinished()) - { - for(int i=0;i<16;++i) - ((QLabel*)ui->twChannels->cellWidget(i,3))->setText(""); - return; - } - for(int i=0;i<16;++i) - { - char data[128],nm[24]; - int b,p; - qmpMainWindow::getInstance()->getPlayer()->getChannelPreset(i,&b,&p,nm); - sprintf(data,"%d:%d %s",b,p,nm); - ((QLabel*)ui->twChannels->cellWidget(i,3))->setText(data); - } -} - -void qmpChannelsWindow::channelMSChanged() -{ - for(int i=0;i<16;++i) - { - QCheckBox *m,*s; - m=(QCheckBox*)ui->twChannels->cellWidget(i,0); - s=(QCheckBox*)ui->twChannels->cellWidget(i,1); - if(m->isChecked()&&s->isChecked())s->setChecked(false); - qmpMainWindow::getInstance()->getPlayer()->setMute(i,m->isChecked()); - qmpMainWindow::getInstance()->getPlayer()->setSolo(i,s->isChecked()); - } -} - -qmpChannelsWindow::~qmpChannelsWindow() -{ - delete ui; -} - -void qmpChannelsWindow::on_pbUnmute_clicked() -{ - for(int i=0;i<16;++i) - { - ((QCheckBox*)ui->twChannels->cellWidget(i,0))->setChecked(false); - qmpMainWindow::getInstance()->getPlayer()->setMute(i,false); - } -} - -void qmpChannelsWindow::on_pbUnsolo_clicked() -{ - for(int i=0;i<16;++i) - { - ((QCheckBox*)ui->twChannels->cellWidget(i,1))->setChecked(false); - qmpMainWindow::getInstance()->getPlayer()->setSolo(i,false); - } -} - -void qmpChannelsWindow::showPresetWindow(int chid) -{ - pselectw->show(); - pselectw->setupWindow(chid); -} - -void qmpChannelsWindow::showChannelEditorWindow(int chid) -{ - ceditw->show(); - ceditw->setupWindow(chid); -} diff --git a/qmpchannelswindow.hpp b/qmpchannelswindow.hpp deleted file mode 100644 index f0591b6..0000000 --- a/qmpchannelswindow.hpp +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef QMPCHANNELSWINDOW_H -#define QMPCHANNELSWINDOW_H - -#include -#include -#include -#include -#include -#include -#include "qmppresetselect.hpp" -#include "qmpchanneleditor.hpp" - -namespace Ui { - class qmpChannelsWindow; -} - -class QDCLabel:public QLabel -{ - Q_OBJECT - private: - int id; - protected: - void mouseDoubleClickEvent(QMouseEvent *event){event->accept();emit onDoubleClick(id);} - public: - QDCLabel(QString s):QLabel(s){id=-1;} - void setID(int _id){id=_id;} - signals: - void onDoubleClick(int id); -}; - -class QDCPushButton:public QPushButton -{ - Q_OBJECT - private: - int id; - protected: - void mousePressEvent(QMouseEvent *event){QPushButton::mousePressEvent(event);emit onClick(id);} - public: - QDCPushButton(QString s):QPushButton(s){id=-1;} - void setID(int _id){id=_id;} - signals: - void onClick(int id); -}; - -class qmpChannelsWindow:public QDialog -{ - Q_OBJECT - - public: - explicit qmpChannelsWindow(QWidget *parent = 0); - ~qmpChannelsWindow(); - void showEvent(QShowEvent *event); - void closeEvent(QCloseEvent *event); - void moveEvent(QMoveEvent *event); - signals: - void dialogClosing(); - public slots: - void channelWindowsUpdate(); - void channelMSChanged(); - void showPresetWindow(int chid); - void showChannelEditorWindow(int chid); - void on_pbUnmute_clicked(); - void on_pbUnsolo_clicked(); - - private: - Ui::qmpChannelsWindow *ui; - qmpPresetSelector *pselectw; - qmpChannelEditor *ceditw; -}; - -#endif // QMPCHANNELSWINDOW_H diff --git a/qmpchannelswindow.ui b/qmpchannelswindow.ui deleted file mode 100644 index a8b43cb..0000000 --- a/qmpchannelswindow.ui +++ /dev/null @@ -1,146 +0,0 @@ - - - qmpChannelsWindow - - - - 0 - 0 - 580 - 410 - - - - - 580 - 410 - - - - - 580 - 16777215 - - - - Channels - - - - - - - - - 0 - 0 - - - - true - - - QAbstractItemView::NoSelection - - - false - - - 16 - - - 5 - - - - - - - - - - - - - - - - - - - - M - - - - - S - - - - - Device - - - - - Preset - - - - - ... - - - - - - - - - - - - - - - - - Save - - - - 16 - 16 - - - - - - - - Load - - - - - - - Unmute All - - - - - - - Unsolo All - - - - - - - - - - diff --git a/qmpefxwindow.cpp b/qmpefxwindow.cpp deleted file mode 100644 index 7d9c08e..0000000 --- a/qmpefxwindow.cpp +++ /dev/null @@ -1,198 +0,0 @@ -#include -#include "qmpefxwindow.hpp" -#include "ui_qmpefxwindow.h" -#include "qmpmainwindow.hpp" - -qmpEfxWindow::qmpEfxWindow(QWidget *parent) : - QDialog(parent), - ui(new Ui::qmpEfxWindow) -{ - ui->setupUi(this);initialized=false; - styl=new QDialSkulptureStyle(); - QList dials=findChildren(); - for(int i=0;isetStyle(styl); - connect(this,SIGNAL(dialogClosing()),parent,SLOT(dialogClosed())); - //stub. read these from settings after the setting module is implemented - 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",FLUID_REVERB_DEFAULT_ROOMSIZE).toDouble(); - rd=settings->value("Effects/ReverbDamp",FLUID_REVERB_DEFAULT_DAMP).toDouble(); - rw=settings->value("Effects/ReverbWidth",FLUID_REVERB_DEFAULT_WIDTH).toDouble(); - rl=settings->value("Effects/ReverbLevel",FLUID_REVERB_DEFAULT_LEVEL).toDouble(); - - cfb=settings->value("Effects/ChorusFeedbk",FLUID_CHORUS_DEFAULT_N).toInt(); - cl=settings->value("Effects/ChorusLevel",FLUID_CHORUS_DEFAULT_LEVEL).toDouble(); - cr=settings->value("Effects/ChorusRate",FLUID_CHORUS_DEFAULT_SPEED).toDouble(); - cd=settings->value("Effects/ChorusDepth",FLUID_CHORUS_DEFAULT_DEPTH).toDouble(); - ct=settings->value("Effects/ChorusType",FLUID_CHORUS_DEFAULT_TYPE).toInt(); -} - -qmpEfxWindow::~qmpEfxWindow() -{ - delete styl; - delete ui; -} - -void qmpEfxWindow::closeEvent(QCloseEvent *event) -{ - setVisible(false); - if(!qmpMainWindow::getInstance()->isFinalizing()&&qmpSettingsWindow::getSettingsIntf()->value("Behavior/DialogStatus","").toInt()) - { - qmpSettingsWindow::getSettingsIntf()->setValue("DialogStatus/EfxWShown",0); - } - emit dialogClosing(); - event->accept(); -} - -void qmpEfxWindow::showEvent(QShowEvent *event) -{ - //CMidiPlayer* player=qmpMainWindow::getInstance()->getPlayer(); - //These parameters will never be modified outside this window... - /*if(initialized) - { - player->getReverbPara(&rr,&rd,&rw,&rl); - player->getChorusPara(&cfb,&cl,&cr,&cd,&ct); - }*/ - ui->sbRoom->setValue((int)round(rr*100));ui->dRoom->setValue((int)round(rr*100)); - ui->sbDamp->setValue((int)round(rd*100));ui->dDamp->setValue((int)round(rd*100)); - ui->sbWidth->setValue((int)round(rw*100));ui->dWidth->setValue((int)round(rw*100)); - ui->sbLevelR->setValue((int)round(rl*100));ui->dLevelR->setValue((int)round(rl*100)); - - ui->sbFeedBack->setValue(cfb);ui->dFeedBack->setValue(cfb); - ui->sbRate->setValue(cr);ui->dRate->setValue((int)round(cr*100)); - ui->sbDepth->setValue(cd);ui->dDepth->setValue((int)round(cd*10)); - ui->sbLevelC->setValue((int)round(cl*100));ui->dLevelC->setValue((int)round(cl*100)); - 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("Behavior/DialogStatus","").toInt()) - { - qmpSettingsWindow::getSettingsIntf()->setValue("DialogStatus/EfxWShown",1); - } - event->accept(); -} - -void qmpEfxWindow::moveEvent(QMoveEvent *event) -{ - if(qmpSettingsWindow::getSettingsIntf()->value("Behavior/DialogStatus","").toInt()) - { - qmpSettingsWindow::getSettingsIntf()->setValue("DialogStatus/EfxW",event->pos()); - } -} - -void qmpEfxWindow::sendEfxChange() -{ - if(!qmpMainWindow::getInstance()||!initialized)return; - rr=ui->sbRoom->value()/100.;rd=ui->sbDamp->value()/100.; - rw=ui->sbWidth->value()/100.;rl=ui->sbLevelR->value()/100.; - ct=ui->rbSine->isChecked()?FLUID_CHORUS_MOD_SINE:FLUID_CHORUS_MOD_TRIANGLE; - cfb=ui->sbFeedBack->value();cl=ui->sbLevelC->value()/100.; - cr=ui->sbRate->value();cd=ui->sbDepth->value(); - CMidiPlayer* player=qmpMainWindow::getInstance()->getPlayer(); - player->setReverbPara(ui->cbEnabledR->isChecked()?1:0,rr,rd,rw,rl); - player->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); -} - -void qmpEfxWindow::dailValueChange() -{ - if(!initialized)return; - ui->sbRoom->setValue(ui->dRoom->value()); - ui->sbDamp->setValue(ui->dDamp->value()); - ui->sbWidth->setValue(ui->dWidth->value()); - ui->sbLevelR->setValue(ui->dLevelR->value()); - ui->sbFeedBack->setValue(ui->dFeedBack->value()); - ui->sbRate->setValue(ui->dRate->value()/100.); - ui->sbDepth->setValue(ui->dDepth->value()/10.); - ui->sbLevelC->setValue(ui->dLevelC->value()); - sendEfxChange(); -} - -void qmpEfxWindow::spinValueChange() -{ - if(!initialized)return; - ui->dRoom->setValue(ui->sbRoom->value()); - ui->dDamp->setValue(ui->sbDamp->value()); - ui->dWidth->setValue(ui->sbWidth->value()); - ui->dLevelR->setValue(ui->sbLevelR->value()); - ui->dFeedBack->setValue(ui->sbFeedBack->value()); - ui->dRate->setValue((int)(ui->sbRate->value()*100)); - ui->dDepth->setValue((int)(ui->sbDepth->value()*10)); - ui->dLevelC->setValue(ui->sbLevelC->value()); - sendEfxChange(); -} - -void qmpEfxWindow::on_dRoom_valueChanged() -{dailValueChange();} - -void qmpEfxWindow::on_dDamp_valueChanged() -{dailValueChange();} - -void qmpEfxWindow::on_dWidth_valueChanged() -{dailValueChange();} - -void qmpEfxWindow::on_dLevelR_valueChanged() -{dailValueChange();} - -void qmpEfxWindow::on_dFeedBack_valueChanged() -{dailValueChange();} - -void qmpEfxWindow::on_dRate_valueChanged() -{dailValueChange();} - -void qmpEfxWindow::on_dDepth_valueChanged() -{dailValueChange();} - -void qmpEfxWindow::on_dLevelC_valueChanged() -{dailValueChange();} - -void qmpEfxWindow::on_sbRoom_valueChanged(QString s) -{s=QString();spinValueChange();} - -void qmpEfxWindow::on_sbDamp_valueChanged(QString s) -{s=QString();spinValueChange();} - -void qmpEfxWindow::on_sbWidth_valueChanged(QString s) -{s=QString();spinValueChange();} - -void qmpEfxWindow::on_sbLevelR_valueChanged(QString s) -{s=QString();spinValueChange();} - -void qmpEfxWindow::on_sbFeedBack_valueChanged(QString s) -{s=QString();spinValueChange();} - -void qmpEfxWindow::on_sbRate_valueChanged(QString s) -{s=QString();spinValueChange();} - -void qmpEfxWindow::on_sbDepth_valueChanged(QString s) -{s=QString();spinValueChange();} - -void qmpEfxWindow::on_sbLevelC_valueChanged(QString s) -{s=QString();spinValueChange();} - -void qmpEfxWindow::on_cbEnabledC_stateChanged() -{sendEfxChange();} - -void qmpEfxWindow::on_cbEnabledR_stateChanged() -{sendEfxChange();} - -void qmpEfxWindow::on_rbSine_toggled() -{sendEfxChange();} - -void qmpEfxWindow::on_rbTriangle_toggled() -{sendEfxChange();} diff --git a/qmpefxwindow.hpp b/qmpefxwindow.hpp deleted file mode 100644 index 2a080f0..0000000 --- a/qmpefxwindow.hpp +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef QMPEFXWINDOW_HPP -#define QMPEFXWINDOW_HPP - -#include -#include -#include -#include - -#include "qdialskulpturestyle.hpp" - -namespace Ui { - class qmpEfxWindow; -} - -class qmpEfxWindow : public QDialog -{ - Q_OBJECT - - public: - explicit qmpEfxWindow(QWidget *parent=0); - ~qmpEfxWindow(); - void closeEvent(QCloseEvent *event); - void showEvent(QShowEvent *event); - void moveEvent(QMoveEvent *event); - void sendEfxChange(); - - signals: - void dialogClosing(); - - private slots: - void on_dRoom_valueChanged(); - void on_dDamp_valueChanged(); - void on_dWidth_valueChanged(); - void on_dLevelR_valueChanged(); - void on_dFeedBack_valueChanged(); - void on_dRate_valueChanged(); - void on_dDepth_valueChanged(); - void on_dLevelC_valueChanged(); - void on_sbRoom_valueChanged(QString s); - void on_sbDamp_valueChanged(QString s); - void on_sbWidth_valueChanged(QString s); - void on_sbLevelR_valueChanged(QString s); - void on_sbFeedBack_valueChanged(QString s); - void on_sbRate_valueChanged(QString s); - void on_sbDepth_valueChanged(QString s); - void on_sbLevelC_valueChanged(QString s); - void on_cbEnabledC_stateChanged(); - void on_cbEnabledR_stateChanged(); - void on_rbSine_toggled(); - void on_rbTriangle_toggled(); - - private: - void dailValueChange(); - void spinValueChange(); - Ui::qmpEfxWindow *ui; - double rr,rd,rw,rl; - int cfb,ct,initialized; - double cl,cr,cd; - QCommonStyle* styl; -}; - -#endif // QMPEFXWINDOW_HPP diff --git a/qmpefxwindow.ui b/qmpefxwindow.ui deleted file mode 100644 index 4a1e0c6..0000000 --- a/qmpefxwindow.ui +++ /dev/null @@ -1,478 +0,0 @@ - - - qmpEfxWindow - - - - 0 - 0 - 546 - 177 - - - - - 546 - 177 - - - - - 546 - 177 - - - - Effects - - - - - - Reverb - - - - - 80 - 4 - 21 - 24 - - - - - - - - - - 10 - 30 - 50 - 51 - - - - 120 - - - true - - - - - - 200 - 30 - 50 - 51 - - - - 100 - - - true - - - - - - 10 - 103 - 50 - 51 - - - - 100 - - - true - - - - - - 200 - 103 - 50 - 51 - - - - 100 - - - true - - - - - - 60 - 30 - 41 - 20 - - - - Room - - - - - - 60 - 50 - 51 - 21 - - - - 120 - - - - - - 140 - 30 - 51 - 20 - - - - Damp - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - 140 - 50 - 56 - 21 - - - - 100 - - - - - - 60 - 100 - 51 - 20 - - - - Width - - - - - - 60 - 120 - 56 - 21 - - - - 100 - - - - - - 145 - 100 - 51 - 20 - - - - Level - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - 140 - 120 - 56 - 21 - - - - 100 - - - - - - - - Chorus - - - - - 80 - 4 - 21 - 24 - - - - - - - - - - 10 - 30 - 50 - 51 - - - - 99 - - - true - - - - - - 200 - 30 - 50 - 51 - - - - 29 - - - 500 - - - 29 - - - true - - - - - - 10 - 103 - 50 - 51 - - - - 210 - - - true - - - - - - 200 - 103 - 50 - 51 - - - - 100 - - - true - - - - - - 60 - 30 - 71 - 20 - - - - Feedback - - - - - - 60 - 50 - 51 - 21 - - - - 99 - - - - - - 140 - 30 - 51 - 20 - - - - Rate - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - 60 - 100 - 51 - 20 - - - - Depth - - - - - - 145 - 100 - 51 - 20 - - - - Level - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - 140 - 120 - 56 - 21 - - - - 100 - - - - - - 137 - 50 - 61 - 21 - - - - 0.290000000000000 - - - 5.000000000000000 - - - 0.100000000000000 - - - - - - 35 - 77 - 41 - 20 - - - - LFO - - - - - - 70 - 77 - 61 - 20 - - - - Sine - - - - - - 145 - 77 - 91 - 20 - - - - Trian&gle - - - - - - 60 - 120 - 51 - 21 - - - - 1 - - - 21.000000000000000 - - - 0.100000000000000 - - - - - - - - - diff --git a/qmphelpwindow.cpp b/qmphelpwindow.cpp deleted file mode 100644 index 10cf083..0000000 --- a/qmphelpwindow.cpp +++ /dev/null @@ -1,31 +0,0 @@ -#include -#include "qmphelpwindow.hpp" -#include "ui_qmphelpwindow.h" - -qmpHelpWindow::qmpHelpWindow(QWidget *parent) : - QDialog(parent), - ui(new Ui::qmpHelpWindow) -{ - ui->setupUi(this); - ui->textBrowser->setSearchPaths(QStringList(QString(":/doc"))+QStringList(QString(":/img"))); - ui->textBrowser->setSource(QUrl("qrc:///doc/index.html")); -} - -qmpHelpWindow::~qmpHelpWindow() -{ - delete ui; -} - -void qmpHelpWindow::on_textBrowser_sourceChanged(const QUrl &src) -{ - if(src.fileName()==QString("version.html")) - { - QString s=ui->textBrowser->toHtml(); - s.replace("CT_QT_VERSION_STR",QT_VERSION_STR); - s.replace("RT_QT_VERSION_STR",qVersion()); - s.replace("CT_FLUIDSYNTH_VERSION",FLUIDSYNTH_VERSION); - s.replace("RT_FLUIDSYNTH_VERSION",fluid_version_str()); - s.replace("APP_VERSION",APP_VERSION); - ui->textBrowser->setHtml(s); - } -} diff --git a/qmphelpwindow.hpp b/qmphelpwindow.hpp deleted file mode 100644 index c2052b2..0000000 --- a/qmphelpwindow.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef QMPHELPWINDOW_H -#define QMPHELPWINDOW_H - -#include -#define APP_VERSION "0.7.0" - -namespace Ui { - class qmpHelpWindow; -} - -class qmpHelpWindow : public QDialog -{ - Q_OBJECT - - public: - explicit qmpHelpWindow(QWidget *parent = 0); - ~qmpHelpWindow(); - - private slots: - void on_textBrowser_sourceChanged(const QUrl &src); - - private: - Ui::qmpHelpWindow *ui; -}; - -#endif // QMPHELPWINDOW_H diff --git a/qmphelpwindow.ui b/qmphelpwindow.ui deleted file mode 100644 index fd21b5f..0000000 --- a/qmphelpwindow.ui +++ /dev/null @@ -1,34 +0,0 @@ - - - qmpHelpWindow - - - - 0 - 0 - 640 - 360 - - - - - 640 - 360 - - - - Help - - - - - - true - - - - - - - - diff --git a/qmpimidimapper.hpp b/qmpimidimapper.hpp deleted file mode 100644 index d35dbb9..0000000 --- a/qmpimidimapper.hpp +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef QMPIMIDIMAPPER_H -#define QMPIMIDIMAPPER_H -class qmpIMidiMapper -{ - virtual void deviceInit(int id)=0; - virtual void deviceDeinit(int id)=0; - virtual void noteOn(int ch,int key,int vel)=0; - virtual void noteOff(int ch,int key)=0; - virtual void ctrlChange(int ch,int cc,int val)=0; - virtual void progChange(int ch,int val)=0; - virtual void pitchBend(int ch,int val)=0; - virtual void sysEx(int length,const char* data)=0; - virtual static int enumDevices()=0; - virtual static char* deviceName(int id)=0; -}; -#endif // QMPIMIDIMAPPER_H diff --git a/qmpinfowindow.cpp b/qmpinfowindow.cpp deleted file mode 100644 index 689a756..0000000 --- a/qmpinfowindow.cpp +++ /dev/null @@ -1,57 +0,0 @@ -#include -#include "qmpinfowindow.hpp" -#include "ui_qmpinfowindow.h" -#include "qmpmainwindow.hpp" -#include "qmpsettingswindow.hpp" - -const char* minors="abebbbf c g d a e b f#c#g#d#a#"; -const char* majors="CbGbDbAbEbBbF C G D A E B F#C#"; -const char* standards="? GM GM2GS XG "; - -qmpInfoWindow::qmpInfoWindow(QWidget *parent) : - QDialog(parent), - ui(new Ui::qmpInfoWindow) -{ - ui->setupUi(this); -} - -qmpInfoWindow::~qmpInfoWindow() -{ - delete ui; -} - -void qmpInfoWindow::updateInfo() -{ - char str[256]; - CMidiPlayer* player=qmpMainWindow::getInstance()->getPlayer(); - QSettings* settings=qmpSettingsWindow::getSettingsIntf(); - ui->lbFileName->setText(QString("File name: ")+qmpMainWindow::getInstance()->getFileName()); - if(player->getTitle()) - { - if(settings->value("Midi/TextEncoding","").toString()!="Unicode") - ui->lbTitle->setText(QString("Title: ")+ - QTextCodec::codecForName(settings->value("Midi/TextEncoding","").toString().toStdString().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") - ui->lbCopyright->setText(QString("Copyright: ")+ - QTextCodec::codecForName(settings->value("Midi/TextEncoding","").toString().toStdString().c_str())->toUnicode(player->getCopyright())); - else - ui->lbCopyright->setText(QString("Copyright: ")+player->getCopyright()); - } - else ui->lbCopyright->setText(QString("Copyright: ")); - ui->lbTempo->setText(QString("Tempo: ")+QString::number(player->getTempo(),'g',5)); - int t,r;player->getCurrentKeySignature(&t);r=(int8_t)((t>>8)&0xFF)+7; - strncpy(str,t&0xFF?minors+2*r:majors+2*r,2);str[2]='\0'; - ui->lbKeySig->setText(QString("Key Sig.: ")+str); - player->getCurrentTimeSignature(&t,&r);sprintf(str,"Time Sig.: %d/%d",t,r); - ui->lbTimeSig->setText(str); - sprintf(str,"Note count: %u",player->getFileNoteCount()); - ui->lbNoteCount->setText(str); - strncpy(str,standards+player->getFileStandard()*3,3);str[3]='\0'; - ui->lbFileStandard->setText(QString("File standard: ")+str); -} diff --git a/qmpinfowindow.hpp b/qmpinfowindow.hpp deleted file mode 100644 index 9a1e389..0000000 --- a/qmpinfowindow.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef QMPINFOWINDOW_HPP -#define QMPINFOWINDOW_HPP - -#include - -namespace Ui { - class qmpInfoWindow; -} - -class qmpInfoWindow : public QDialog -{ - Q_OBJECT - - public: - explicit qmpInfoWindow(QWidget *parent = 0); - ~qmpInfoWindow(); - public slots: - void updateInfo(); - - private: - Ui::qmpInfoWindow *ui; -}; - -#endif // QMPINFOWINDOW_HPP diff --git a/qmpinfowindow.ui b/qmpinfowindow.ui deleted file mode 100644 index 664531a..0000000 --- a/qmpinfowindow.ui +++ /dev/null @@ -1,91 +0,0 @@ - - - qmpInfoWindow - - - - 0 - 0 - 400 - 142 - - - - - 400 - 142 - - - - File Information - - - - - - File name: - - - - - - - - - Tempo: - - - - - - - Key Sig.: - - - - - - - Time Sig.: - - - - - - - - - Title: - - - - - - - Copyright: - - - - - - - - - Note count: - - - - - - - File standard: - - - - - - - - - - diff --git a/qmpmainwindow.cpp b/qmpmainwindow.cpp deleted file mode 100644 index aad0161..0000000 --- a/qmpmainwindow.cpp +++ /dev/null @@ -1,510 +0,0 @@ -#include -#include -#include -#include -#include -#include "qmpmainwindow.hpp" -#include "ui_qmpmainwindow.h" -#include "qmpmidiplay.hpp" -#ifdef _WIN32 -#include -#endif - -qmpMainWindow* qmpMainWindow::ref=NULL; - -qmpMainWindow::qmpMainWindow(QWidget *parent) : - QMainWindow(parent), - ui(new Ui::qmpMainWindow) -{ - ui->setupUi(this); - ui->lbFileName->setText("");ref=this; - playing=false;stopped=true;dragging=false; - settingsw=new qmpSettingsWindow(this); - plistw=new qmpPlistWindow(this); - chnlw=new qmpChannelsWindow(this); - efxw=new qmpEfxWindow(this); - infow=new qmpInfoWindow(this); - helpw=new qmpHelpWindow(this); - timer=new QTimer(this); - fnA1=new QAction("File Information",ui->lbFileName); - fnA2=new QAction("Render to Wave",ui->lbFileName); - ui->lbFileName->addAction(fnA1); - ui->lbFileName->addAction(fnA2); - singleFS=qmpSettingsWindow::getSettingsIntf()->value("Behavior/SingleInstance",0).toInt(); - player=new CMidiPlayer(singleFS); - if(singleFS){player->fluidPreInitialize();playerSetup();player->fluidInitialize(); - for(int i=settingsw->getSFWidget()->count()-1;i>=0;--i) - player->pushSoundFont(settingsw->getSFWidget()->item(i)->text().toStdString().c_str());} - if(qmpSettingsWindow::getSettingsIntf()->value("Behavior/DialogStatus",0).toInt()) - { - QRect g=geometry(); - g.setTopLeft(qmpSettingsWindow::getSettingsIntf()->value("DialogStatus/MainW",QPoint(-999,-999)).toPoint()); - if(g.topLeft()!=QPoint(-999,-999))setGeometry(g); - else setGeometry(QStyle::alignedRect( - Qt::LeftToRight,Qt::AlignCenter,size(), - qApp->desktop()->availableGeometry())); - }show(); - if(qmpSettingsWindow::getSettingsIntf()->value("DialogStatus/PListWShown",0).toInt()) - {ui->pbPList->setChecked(true);on_pbPList_clicked();} - if(qmpSettingsWindow::getSettingsIntf()->value("DialogStatus/ChnlWShown",0).toInt()) - {ui->pbChannels->setChecked(true);on_pbChannels_clicked();} - if(qmpSettingsWindow::getSettingsIntf()->value("DialogStatus/EfxWShown",0).toInt()) - {ui->pbEfx->setChecked(true);on_pbEfx_clicked();} - ui->vsMasterVol->setValue(qmpSettingsWindow::getSettingsIntf()->value("Audio/Gain",50).toInt()); - connect(fnA1,SIGNAL(triggered()),this,SLOT(onfnA1())); - connect(fnA2,SIGNAL(triggered()),this,SLOT(onfnA2())); - connect(timer,SIGNAL(timeout()),this,SLOT(updateWidgets())); - connect(timer,SIGNAL(timeout()),chnlw,SLOT(channelWindowsUpdate())); - connect(timer,SIGNAL(timeout()),infow,SLOT(updateInfo())); -} - -qmpMainWindow::~qmpMainWindow() -{ - delete player; - delete timer; - delete ui; -} - -int qmpMainWindow::pharseArgs(int argc,char** argv) -{ - bool havemidi=false,loadfolder=false; - for(int i=1;iemptyList();} - if(loadfolder||qmpSettingsWindow::getSettingsIntf()->value("Behavior/LoadFolder",0).toInt()) - { - QDirIterator di(QUrl(argv[i]).adjusted(QUrl::RemoveFilename).toString()); - while(di.hasNext()) - { - QString c=di.next(); - if((c.endsWith(".mid")||c.endsWith(".midi"))&&fluid_is_midifile(c.toStdString().c_str())) - plistw->insertItem(c.toStdString().c_str()); - } - } - else - plistw->insertItem(argv[i]); - } - } - if(havemidi)on_pbPlayPause_clicked(); - return 0; -} - -void qmpMainWindow::closeEvent(QCloseEvent *event) -{ - on_pbStop_clicked();fin=true; - efxw->close();chnlw->close(); - plistw->close();infow->close(); - settingsw->close(); - delete helpw;helpw=NULL; - delete efxw;efxw=NULL; - delete chnlw;chnlw=NULL; - delete plistw;plistw=NULL; - delete infow;infow=NULL; - delete settingsw;settingsw=NULL; - event->accept(); -} - -void qmpMainWindow::moveEvent(QMoveEvent *event) -{ - if(qmpSettingsWindow::getSettingsIntf()->value("Behavior/DialogStatus","").toInt()) - { - qmpSettingsWindow::getSettingsIntf()->setValue("DialogStatus/MainW",event->pos()); - } -} -void qmpMainWindow::dropEvent(QDropEvent *event) -{ - QList l=event->mimeData()->urls(); - QStringList sl; - for(int i=0;iinsertItems(sl); -} -void qmpMainWindow::dragEnterEvent(QDragEnterEvent *event) -{ - //if(event->mimeData()->hasFormat("application/x-midi")) - event->acceptProposedAction(); -} - -void qmpMainWindow::updateWidgets() -{ - fnA2->setEnabled(stopped); - if(player->isFinished()&&playerTh) - { - if(!plistw->getRepeat()) - { - timer->stop();stopped=true;playing=false; - fnA2->setEnabled(stopped); - player->playerDeinit();playerTh->join(); - delete playerTh;playerTh=NULL; - if(singleFS)player->playerPanic(true); - chnlw->on_pbUnmute_clicked();chnlw->on_pbUnsolo_clicked(); - ui->pbPlayPause->setIcon(QIcon(":/img/play.png")); - ui->hsTimer->setValue(0); - ui->lbPolyphone->setText("Poly: 0/0"); - ui->lbCurTime->setText("00:00"); - } - else - { - timer->stop();player->playerDeinit();playerTh->join(); - delete playerTh;playerTh=NULL; - ui->hsTimer->setValue(0); - if(singleFS)player->playerPanic(true); - chnlw->on_pbUnmute_clicked();chnlw->on_pbUnsolo_clicked(); - QString fns=plistw->getNextItem(); - ui->lbFileName->setText(QUrl(fns).fileName()); - if(!player->playerLoadFile(fns.toStdString().c_str()))return; - char ts[100]; - sprintf(ts,"%02d:%02d",(int)player->getFtime()/60,(int)player->getFtime()%60); - ui->lbFinTime->setText(ts); - player->playerInit();if(!singleFS){playerSetup();player->fluidInitialize(); - for(int i=settingsw->getSFWidget()->count()-1;i>=0;--i) - player->pushSoundFont(settingsw->getSFWidget()->item(i)->text().toStdString().c_str());} - player->setGain(ui->vsMasterVol->value()/250.);efxw->sendEfxChange(); - player->setWaitVoice(qmpSettingsWindow::getSettingsIntf()->value("Midi/WaitVoice",1).toInt()); - playerTh=new std::thread(&CMidiPlayer::playerThread,player); -#ifdef _WIN32 - SetThreadPriority(playerTh->native_handle(),THREAD_PRIORITY_TIME_CRITICAL); -#endif - st=std::chrono::steady_clock::now();offset=0; - timer->start(100); - } - } - if(renderTh) - { - if(player->isFinished()) - { - renderTh->join();timer->stop(); - ui->centralWidget->setEnabled(true); - delete renderTh;renderTh=NULL; - player->rendererDeinit(); - if(singleFS){player->fluidPreInitialize();playerSetup();player->fluidInitialize();} - } - } - while(!player->isFinished()&&player->getTCeptr()>player->getStamp(ui->hsTimer->value()) - &&ui->hsTimer->value()<=100&&!dragging) - ui->hsTimer->setValue(ui->hsTimer->value()+1); - if(playing) - { - std::chrono::duration elapsed= - std::chrono::duration_cast>(std::chrono::steady_clock::now()-st); - char ts[100]; - sprintf(ts,"%02d:%02d",(int)(elapsed.count()+offset)/60,(int)(elapsed.count()+offset)%60); - ui->lbCurTime->setText(ts); - sprintf(ts,"Poly: %d/%d",player->getPolyphone(),player->getMaxPolyphone()); - ui->lbPolyphone->setText(ts); - } -} - -QString qmpMainWindow::getFileName(){return ui->lbFileName->text();} - -void qmpMainWindow::playerSetup() -{ - fluid_settings_t* fsettings=player->getFluidSettings(); - QSettings* settings=qmpSettingsWindow::getSettingsIntf(); - fluid_settings_setstr(fsettings,"audio.driver",settings->value("Audio/Driver","").toString().toStdString().c_str()); - fluid_settings_setint(fsettings,"audio.period-size",settings->value("Audio/BufSize","").toInt()); - fluid_settings_setint(fsettings,"audio.periods",settings->value("Audio/BufCnt","").toInt()); - fluid_settings_setstr(fsettings,"audio.sample-format",settings->value("Audio/Format","").toString().toStdString().c_str()); - fluid_settings_setint(fsettings,"synth.sample-rate",settings->value("Audio/Frequency","").toInt()); - fluid_settings_setint(fsettings,"synth.polyphony",settings->value("Audio/Polyphony","").toInt()); - fluid_settings_setint(fsettings,"synth.cpu-cores",settings->value("Audio/Threads","").toInt()); - char bsmode[4]; - if(!singleFS&&settings->value("Audio/AutoBS",1).toInt()&&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; - } - 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"); - } - fluid_settings_setstr(fsettings,"synth.midi-bank-select",bsmode); - player->sendSysX(settings->value("Midi/SendSysEx",1).toInt()); -} - -void qmpMainWindow::on_pbPlayPause_clicked() -{ - playing=!playing; - if(stopped) - { - QString fns=plistw->getFirstItem(); - if(!fns.length()) - { - plistw->on_pbAdd_clicked(); - fns=plistw->getFirstItem(); - if(!fns.length())return(void)(playing=false); - } - ui->lbFileName->setText(QUrl(fns).fileName()); - if(!player->playerLoadFile(fns.toStdString().c_str()))return; - char ts[100]; - sprintf(ts,"%02d:%02d",(int)player->getFtime()/60,(int)player->getFtime()%60); - ui->lbFinTime->setText(ts); - player->playerInit();if(!singleFS){playerSetup();player->fluidInitialize(); - for(int i=settingsw->getSFWidget()->count()-1;i>=0;--i) - player->pushSoundFont(settingsw->getSFWidget()->item(i)->text().toStdString().c_str());} - player->setGain(ui->vsMasterVol->value()/250.);efxw->sendEfxChange(); - player->setWaitVoice(qmpSettingsWindow::getSettingsIntf()->value("Midi/WaitVoice",1).toInt()); - playerTh=new std::thread(&CMidiPlayer::playerThread,player); -#ifdef _WIN32 - SetThreadPriority(playerTh->native_handle(),THREAD_PRIORITY_TIME_CRITICAL); -#endif - st=std::chrono::steady_clock::now();offset=0; - timer->start(100); - stopped=false; - } - else - { - if(!playing) - { - player->playerPanic(); - offset=ui->hsTimer->value()/100.*player->getFtime(); - } - else - { - st=std::chrono::steady_clock::now(); - player->setResumed(); - } - player->setTCpaused(!playing); - } - ui->pbPlayPause->setIcon(QIcon(playing?":/img/pause.png":":/img/play.png")); -} - -void qmpMainWindow::on_hsTimer_sliderPressed() -{ - dragging=true; -} - -void qmpMainWindow::on_hsTimer_sliderReleased() -{ - dragging=false; - if(playing) - { - if(ui->hsTimer->value()==100){on_pbNext_clicked();return;} - player->setTCeptr(player->getStamp(ui->hsTimer->value()),ui->hsTimer->value()); - player->playerPanic(); - offset=ui->hsTimer->value()/100.*player->getFtime(); - st=std::chrono::steady_clock::now(); - } - else - { - player->setTCeptr(player->getStamp(ui->hsTimer->value()),ui->hsTimer->value()); - offset=ui->hsTimer->value()/100.*player->getFtime(); - char ts[100]; - sprintf(ts,"%02d:%02d",(int)(offset)/60,(int)(offset)%60); - ui->lbCurTime->setText(ts); - } -} - -void qmpMainWindow::on_vsMasterVol_valueChanged() -{ - if(!stopped)player->setGain(ui->vsMasterVol->value()/250.); - qmpSettingsWindow::getSettingsIntf()->setValue("Audio/Gain",ui->vsMasterVol->value()); -} - -void qmpMainWindow::on_pbStop_clicked() -{ - if(!stopped) - { - timer->stop();stopped=true;playing=false; - player->playerDeinit();fnA2->setEnabled(stopped); - if(singleFS)player->playerPanic(true); - if(playerTh){playerTh->join();delete playerTh;playerTh=NULL;} - chnlw->on_pbUnmute_clicked();chnlw->on_pbUnsolo_clicked(); - ui->pbPlayPause->setIcon(QIcon(":/img/play.png")); - ui->hsTimer->setValue(0); - ui->lbPolyphone->setText("Poly: 0/0"); - ui->lbCurTime->setText("00:00"); - } -} - -void qmpMainWindow::dialogClosed() -{ - if(!plistw->isVisible())ui->pbPList->setChecked(false); - if(!chnlw->isVisible())ui->pbChannels->setChecked(false); - if(!efxw->isVisible())ui->pbEfx->setChecked(false); - if(!settingsw->isVisible())ui->pbSettings->setChecked(false); -} - -void qmpMainWindow::on_pbPList_clicked() -{ - if(ui->pbPList->isChecked()) - { - QRect g=plistw->geometry(); - g.setTopLeft(qmpSettingsWindow::getSettingsIntf()->value("DialogStatus/PListW",QPoint(-999,-999)).toPoint()); - if(g.topLeft()==QPoint(-999,-999)) - g.setTopLeft(window()->mapToGlobal(window()->rect().center())-plistw->rect().center()); - plistw->setGeometry(g); - plistw->show(); - }else plistw->close(); -} - -void qmpMainWindow::on_pbChannels_clicked() -{ - if(ui->pbChannels->isChecked()) - { - QRect g=chnlw->geometry(); - g.setTopLeft(qmpSettingsWindow::getSettingsIntf()->value("DialogStatus/ChnlW",QPoint(-999,-999)).toPoint()); - if(g.topLeft()==QPoint(-999,-999)) - g.setTopLeft(window()->mapToGlobal(window()->rect().center())-chnlw->rect().center()); - chnlw->setGeometry(g); - chnlw->show(); - }else chnlw->close(); -} - -void qmpMainWindow::on_pbPrev_clicked() -{ - timer->stop();player->playerDeinit(); - if(playerTh){playerTh->join();delete playerTh;playerTh=NULL;} - if(singleFS)player->playerPanic(true); - ui->hsTimer->setValue(0);chnlw->on_pbUnmute_clicked();chnlw->on_pbUnsolo_clicked(); - QString fns=plistw->getPrevItem();if(fns.length()==0)return on_pbStop_clicked(); - ui->lbFileName->setText(QUrl(fns).fileName()); - if(!player->playerLoadFile(fns.toStdString().c_str()))return; - char ts[100]; - sprintf(ts,"%02d:%02d",(int)player->getFtime()/60,(int)player->getFtime()%60); - ui->lbFinTime->setText(ts); - player->playerInit();if(!singleFS){playerSetup();player->fluidInitialize(); - for(int i=settingsw->getSFWidget()->count()-1;i>=0;--i) - player->pushSoundFont(settingsw->getSFWidget()->item(i)->text().toStdString().c_str());} - player->setGain(ui->vsMasterVol->value()/250.);efxw->sendEfxChange(); - player->setWaitVoice(qmpSettingsWindow::getSettingsIntf()->value("Midi/WaitVoice",1).toInt()); - playerTh=new std::thread(&CMidiPlayer::playerThread,player); -#ifdef _WIN32 - SetThreadPriority(playerTh->native_handle(),THREAD_PRIORITY_TIME_CRITICAL); -#endif - st=std::chrono::steady_clock::now();offset=0; - timer->start(100); -} - -void qmpMainWindow::on_pbNext_clicked() -{ - timer->stop();player->playerDeinit(); - if(playerTh){playerTh->join();delete playerTh;playerTh=NULL;} - if(singleFS)player->playerPanic(true); - ui->hsTimer->setValue(0);chnlw->on_pbUnmute_clicked();chnlw->on_pbUnsolo_clicked(); - QString fns=plistw->getNextItem();if(fns.length()==0)return on_pbStop_clicked(); - ui->lbFileName->setText(QUrl(fns).fileName()); - if(!player->playerLoadFile(fns.toStdString().c_str()))return; - char ts[100]; - sprintf(ts,"%02d:%02d",(int)player->getFtime()/60,(int)player->getFtime()%60); - ui->lbFinTime->setText(ts); - player->playerInit();if(!singleFS){playerSetup();player->fluidInitialize(); - for(int i=settingsw->getSFWidget()->count()-1;i>=0;--i) - player->pushSoundFont(settingsw->getSFWidget()->item(i)->text().toStdString().c_str());} - player->setGain(ui->vsMasterVol->value()/250.);efxw->sendEfxChange(); - player->setWaitVoice(qmpSettingsWindow::getSettingsIntf()->value("Midi/WaitVoice",1).toInt()); - playerTh=new std::thread(&CMidiPlayer::playerThread,player); -#ifdef _WIN32 - SetThreadPriority(playerTh->native_handle(),THREAD_PRIORITY_TIME_CRITICAL); -#endif - st=std::chrono::steady_clock::now();offset=0; - timer->start(100); -} - -void qmpMainWindow::selectionChanged() -{ - stopped=false;playing=true; - ui->pbPlayPause->setIcon(QIcon(":/img/pause.png")); - timer->stop();player->playerDeinit(); - if(playerTh){playerTh->join();delete playerTh;playerTh=NULL;} - if(singleFS)player->playerPanic(true); - ui->hsTimer->setValue(0); - chnlw->on_pbUnmute_clicked();chnlw->on_pbUnsolo_clicked(); - QString fns=plistw->getSelectedItem(); - ui->lbFileName->setText(QUrl(fns).fileName()); - if(!player->playerLoadFile(fns.toStdString().c_str()))return; - char ts[100]; - sprintf(ts,"%02d:%02d",(int)player->getFtime()/60,(int)player->getFtime()%60); - ui->lbFinTime->setText(ts); - player->playerInit();if(!singleFS){playerSetup();player->fluidInitialize(); - for(int i=settingsw->getSFWidget()->count()-1;i>=0;--i) - player->pushSoundFont(settingsw->getSFWidget()->item(i)->text().toStdString().c_str());} - player->setGain(ui->vsMasterVol->value()/250.);efxw->sendEfxChange(); - player->setWaitVoice(qmpSettingsWindow::getSettingsIntf()->value("Midi/WaitVoice",1).toInt()); - playerTh=new std::thread(&CMidiPlayer::playerThread,player); -#ifdef _WIN32 - SetThreadPriority(playerTh->native_handle(),THREAD_PRIORITY_TIME_CRITICAL); -#endif - st=std::chrono::steady_clock::now();offset=0; - timer->start(100); -} - -void qmpMainWindow::on_pbEfx_clicked() -{ - if(ui->pbEfx->isChecked()) - { - QRect g=efxw->geometry(); - g.setTopLeft(qmpSettingsWindow::getSettingsIntf()->value("DialogStatus/EfxW",QPoint(-999,-999)).toPoint()); - if(g.topLeft()==QPoint(-999,-999)) - g.setTopLeft(window()->mapToGlobal(window()->rect().center())-efxw->rect().center()); - efxw->setGeometry(g); - efxw->show(); - } - else efxw->close(); -} - -void qmpMainWindow::on_lbFileName_customContextMenuRequested(const QPoint &pos) -{ - QMenu menu(ui->lbFileName); - menu.addActions(ui->lbFileName->actions()); - menu.exec(this->pos()+ui->lbFileName->pos()+pos); -} - -void qmpMainWindow::onfnA1() -{ - infow->show(); -} - -void qmpMainWindow::onfnA2() -{ - if(singleFS)player->fluidDeinitialize(); - player->rendererLoadFile((plistw->getSelectedItem()+QString(".wav")).toStdString().c_str()); - playerSetup();player->rendererInit(plistw->getSelectedItem().toStdString().c_str()); - ui->centralWidget->setEnabled(false); - for(int i=settingsw->getSFWidget()->count()-1;i>=0;--i) - player->pushSoundFont(settingsw->getSFWidget()->item(i)->text().toStdString().c_str()); - player->setGain(ui->vsMasterVol->value()/250.);efxw->sendEfxChange();timer->start(100); - renderTh=new std::thread(&CMidiPlayer::rendererThread,player); -} - -void qmpMainWindow::on_pbSettings_clicked() -{ - if(ui->pbSettings->isChecked())settingsw->show();else settingsw->close(); -} - -void qmpMainWindow::on_pushButton_clicked() -{ - helpw->show(); -} diff --git a/qmpmainwindow.hpp b/qmpmainwindow.hpp deleted file mode 100644 index 0b83c39..0000000 --- a/qmpmainwindow.hpp +++ /dev/null @@ -1,90 +0,0 @@ -#ifndef QMPMAINWINDOW_H -#define QMPMAINWINDOW_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "qmpmidiplay.hpp" -#include "qmpplistwindow.hpp" -#include "qmpchannelswindow.hpp" -#include "qmpefxwindow.hpp" -#include "qmpinfowindow.hpp" -#include "qmpsettingswindow.hpp" -#include "qmphelpwindow.hpp" - -namespace Ui { - class qmpMainWindow; -} - -class qmpMainWindow:public QMainWindow -{ - Q_OBJECT - - public: - explicit qmpMainWindow(QWidget *parent = 0); - void closeEvent(QCloseEvent *event); - void moveEvent(QMoveEvent *event); - void dropEvent(QDropEvent *event); - void dragEnterEvent(QDragEnterEvent *event); - ~qmpMainWindow(); - CMidiPlayer* getPlayer(){return player;} - QTimer* getTimer(){return timer;} - bool isFinalizing(){return fin;} - QString getFileName(); - int pharseArgs(int argc,char** argv); - - private slots: - void on_pbPlayPause_clicked(); - void updateWidgets(); - void on_hsTimer_sliderPressed(); - void on_hsTimer_sliderReleased(); - void on_vsMasterVol_valueChanged(); - void on_pbStop_clicked(); - void on_pbPList_clicked(); - void on_pbPrev_clicked(); - void on_pbNext_clicked(); - void on_pbChannels_clicked(); - void on_pbEfx_clicked(); - void on_lbFileName_customContextMenuRequested(const QPoint &pos); - void on_pbSettings_clicked(); - void onfnA1(); - void onfnA2(); - - void on_pushButton_clicked(); - - public slots: - void dialogClosed(); - void selectionChanged(); - - private: - Ui::qmpMainWindow *ui; - QTimer *timer; - bool playing,stopped,dragging,fin,singleFS; - std::thread *playerTh=NULL; - std::thread *renderTh=NULL; - std::chrono::steady_clock::time_point st; - double offset; - CMidiPlayer *player; - qmpPlistWindow *plistw; - qmpChannelsWindow *chnlw; - qmpEfxWindow *efxw; - qmpInfoWindow *infow; - qmpSettingsWindow *settingsw; - qmpHelpWindow *helpw; - - QAction *fnA1,*fnA2; - void playerSetup(); - - private: - static qmpMainWindow* ref; - public: static qmpMainWindow* getInstance(){return ref;} -}; - -#endif // QMPMAINWINDOW_H diff --git a/qmpmainwindow.ui b/qmpmainwindow.ui deleted file mode 100644 index 0764e09..0000000 --- a/qmpmainwindow.ui +++ /dev/null @@ -1,413 +0,0 @@ - - - qmpMainWindow - - - - 0 - 0 - 435 - 245 - - - - - 435 - 245 - - - - - 435 - 245 - - - - true - - - QMidiPlayer - - - - :/img/qmidiplyr.png:/img/qmidiplyr.png - - - - - - 30 - 20 - 311 - 41 - - - - - 18 - - - - Qt::CustomContextMenu - - - somefile.mid - - - Qt::AlignCenter - - - - - - 20 - 90 - 321 - 20 - - - - 100 - - - 0 - - - Qt::Horizontal - - - - - - 20 - 110 - 61 - 36 - - - - - - - - :/img/play.png:/img/play.png - - - - 32 - 32 - - - - - - - 80 - 110 - 61 - 36 - - - - - - - - :/img/stop.png:/img/stop.png - - - - 32 - 32 - - - - - - - 140 - 110 - 61 - 36 - - - - - - - - :/img/prev.png:/img/prev.png - - - - 32 - 32 - - - - - - - 200 - 110 - 61 - 36 - - - - - - - - :/img/next.png:/img/next.png - - - - 32 - 32 - - - - - - - 280 - 110 - 61 - 36 - - - - - - - - :/img/settings.png:/img/settings.png - - - - 32 - 32 - - - - true - - - - - - 20 - 160 - 151 - 36 - - - - text-align:left - - - Channels - - - - :/img/channel.png:/img/channel.png - - - - 32 - 32 - - - - true - - - - - - 190 - 160 - 151 - 36 - - - - text-align:left - - - Playlist - - - - :/img/list.png:/img/list.png - - - - 32 - 32 - - - - true - - - false - - - false - - - - - - 20 - 200 - 151 - 36 - - - - text-align:left - - - Effects - - - - :/img/effects.png:/img/effects.png - - - - 32 - 32 - - - - true - - - - - - 190 - 200 - 151 - 36 - - - - text-align:left - - - Visualization - - - - :/img/visualization.png:/img/visualization.png - - - - 32 - 32 - - - - - - - 320 - 20 - 111 - 20 - - - - <html><head/><body><p>Poly: 0/0</p></body></html> - - - Qt::AlignCenter - - - - - - 370 - 50 - 20 - 160 - - - - 100 - - - 50 - - - Qt::Vertical - - - - - - 360 - 210 - 61 - 20 - - - - Master - - - - - - 20 - 70 - 66 - 20 - - - - 00:00 - - - - - - 270 - 70 - 66 - 20 - - - - 00:00 - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - 0 - 0 - 21 - 21 - - - - ? - - - - - - - - - - diff --git a/qmpmidiplay.cpp b/qmpmidiplay.cpp deleted file mode 100644 index 6f69e33..0000000 --- a/qmpmidiplay.cpp +++ /dev/null @@ -1,404 +0,0 @@ -#include -#include -#include -#include -#include "qmpmidiplay.hpp" -#ifdef _WIN32 -#include -uint64_t pf; -#endif -void CMidiPlayer::fluidPreInitialize() -{ - settings=new_fluid_settings(); -} -void CMidiPlayer::fluidInitialize() -{ - synth=new_fluid_synth(settings); - adriver=new_fluid_audio_driver(settings,synth); - fluid_synth_set_chorus(synth,FLUID_CHORUS_DEFAULT_N,FLUID_CHORUS_DEFAULT_LEVEL, - FLUID_CHORUS_DEFAULT_SPEED,FLUID_CHORUS_DEFAULT_DEPTH, - FLUID_CHORUS_DEFAULT_TYPE); -#ifndef _WIN32 - if(!singleInstance) - { - if(midiFile->getStandard()==4) - fluid_synth_set_channel_type(synth,9,CHANNEL_TYPE_MELODIC); - else if(midiFile->getStandard()==1) - fluid_synth_set_channel_type(synth,9,CHANNEL_TYPE_DRUM); - else - { - fluid_synth_set_channel_type(synth,9,CHANNEL_TYPE_DRUM); - fluid_synth_bank_select(synth,9,128); - } - } -#endif -} -void CMidiPlayer::fluidDeinitialize() -{ - if(!synth||!adriver||!settings)return; - delete_fluid_settings(settings); - delete_fluid_audio_driver(adriver); - delete_fluid_synth(synth); - settings=NULL;synth=NULL;adriver=NULL; -} -void CMidiPlayer::processEvent(const SEvent *e) -{ - switch(e->type&0xF0) - { - case 0x80://Note off - fluid_synth_noteoff(synth,e->type&0x0F,e->p1); - break; - case 0x90://Note on - if((mute>>(e->type&0x0F))&1)break;//muted - if(solo&&!((solo>>(e->type&0x0F))&1))break; - fluid_synth_noteon(synth,e->type&0x0F,e->p1,e->p2); - break; - case 0xB0://CC - if(e->p1==100)rpnid=e->p2; - if(e->p1==6)rpnval=e->p2; - if(~rpnid&&~rpnval) - { - if(rpnid==0)fluid_synth_pitch_wheel_sens(synth,e->type&0x0F,rpnval); - rpnid=rpnval=-1; - } - fluid_synth_cc(synth,e->type&0x0F,e->p1,e->p2); - break; - case 0xC0://PC - fluid_synth_program_change(synth,e->type&0x0F,e->p1); - break; - case 0xE0://PW - fluid_synth_pitch_bend(synth,e->type&0x0F,e->p1); - break; - case 0xF0://Meta/SysEx - if((e->type&0x0F)==0x0F) - { - switch(e->p1) - { - case 0x51: - ctempo=e->p2;dpt=ctempo*1000/divs; - break; - case 0x58: - ctsn=e->p2>>24; - ctsd=1<<((e->p2>>16)&0xFF); - break; - case 0x59: - cks=e->p2; - break; - case 0x01:case 0x02:case 0x03: - case 0x04:case 0x05:case 0x06: - case 0x07: - //if(e->str)puts(e->str); - break; - } - } - if((e->type&0x0F)==0x00||(e->type&0x0F)==07) - { - int io=0; - if(sendSysEx)fluid_synth_sysex(synth,e->str,e->p1,NULL,&io,NULL,0); - } - break; - } -} -void CMidiPlayer::processEventStub(const SEvent *e) -{ - switch(e->type&0xF0) - { - case 0xB0://CC - if(e->p1==100)rpnid=e->p2; - if(e->p1==6)rpnval=e->p2; - if(~rpnid&&~rpnval) - { - if(rpnid==0)ccc[e->type&0x0F][134]=rpnval; - rpnid=rpnval=-1; - } - ccc[e->type&0x0F][e->p1]=e->p2; - break; - case 0xC0://PC - ccc[e->type&0x0F][128]=e->p1; - break; - case 0xD0://CP - ccc[e->type&0x0F][129]=e->p1; - break; - case 0xE0://PW - ccc[e->type&0x0F][130]=e->p1; - break; - case 0xF0://Meta/SysEx - if((e->type&0x0F)==0x0F) - { - switch(e->p1) - { - case 0x51: - ctempo=e->p2;dpt=ctempo*1000/divs; - ccc[0][131]=dpt; - break; - case 0x58: - ccc[0][132]=e->p2; - break; - case 0x59: - ccc[0][133]=e->p2; - break; - } - } - break; - } -} -#ifdef _WIN32 -void w32usleep(uint64_t t) -{ - uint64_t st=0,ct=0; - timeBeginPeriod(1); - QueryPerformanceCounter((LARGE_INTEGER*)&st); - do{ - if(t>10000+(ct-st)*1000000/pf)Sleep((t-(ct-st)*1000000/pf)/2000); - else if(t>5000+(ct-st)*1000000/pf)Sleep(1); - else std::this_thread::yield(); - QueryPerformanceCounter((LARGE_INTEGER*)&ct); - }while((ct-st)*1000000getEvent(0)->time;tceptrgetEventCount();) - { - while(tcpaused)std::this_thread::sleep_for(std::chrono::milliseconds(100)); - while(!tcstop&&midiFile&&tceptrgetEventCount()&&ct==midiFile->getEvent(tceptr)->time) - processEvent(midiFile->getEvent(tceptr++)); - if(tcstop||!midiFile||tceptr>=midiFile->getEventCount())break; - if(resumed)resumed=false; - else -#if 0 - w32usleep((midiFile->getEvent(tceptr)->time-ct)*(dpt/1000)); -#else - std::this_thread::sleep_for(std::chrono::nanoseconds(midiFile->getEvent(tceptr)->time-ct)*dpt); -#endif - if(tcstop||!midiFile)break; - ct=midiFile->getEvent(tceptr)->time; - } - while(!tcstop&&synth&&(waitvoice&&fluid_synth_get_active_voice_count(synth)>0))std::this_thread::sleep_for(std::chrono::milliseconds(2)); - finished=1; -} -void CMidiPlayer::fileTimer1Pass() -{ - ftime=.0;ctempo=0x7A120;dpt=ctempo*1000/divs; - for(uint32_t eptr=0,ct=midiFile->getEvent(0)->time;eptrgetEventCount();) - { - while(eptrgetEventCount()&&ct==midiFile->getEvent(eptr)->time) - processEventStub(midiFile->getEvent(eptr++)); - if(eptr>=midiFile->getEventCount())break; - ftime+=(midiFile->getEvent(eptr)->time-ct)*dpt/1e9; - ct=midiFile->getEvent(eptr)->time; - } -} -void CMidiPlayer::fileTimer2Pass() -{ - double ctime=.0;uint32_t c=1;ctempo=0x7A120;dpt=ctempo*1000/divs; - memset(stamps,0,sizeof(stamps));memset(ccstamps,0,sizeof(ccstamps)); - memset(ccc,0,sizeof(ccc));rpnid=rpnval=-1;for(int i=0;i<16;++i) - { - ccc[i][7]=100;ccc[i][10]=64;ccc[i][11]=127; - 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; - ccc[0][131]=dpt;ccc[0][132]=0x04021808; - ccc[0][133]=0;ccc[0][134]=2; - }if(midiFile->getStandard()!=4)ccc[9][0]=128; - for(int i=0;i<16;++i)for(int j=0;j<135;++j) - ccstamps[0][i][j]=ccc[i][j]; - for(uint32_t eptr=0,ct=midiFile->getEvent(0)->time;eptrgetEventCount();) - { - while(eptrgetEventCount()&&ct==midiFile->getEvent(eptr)->time) - processEventStub(midiFile->getEvent(eptr++)); - if(eptr>=midiFile->getEventCount())break; - ctime+=(midiFile->getEvent(eptr)->time-ct)*dpt/1e9; - while(ctime>ftime*c/100.) - { - for(int i=0;i<16;++i)for(int j=0;j<135;++j) - ccstamps[c][i][j]=ccc[i][j]; - stamps[c++]=eptr; - if(c>100)break; - } - ct=midiFile->getEvent(eptr)->time; - } - while(c<101) - { - for(int i=0;i<16;++i)for(int j=0;j<135;++j) - ccstamps[c][i][j]=ccc[i][j]; - stamps[c++]=midiFile->getEventCount(); - } -} -CMidiPlayer::CMidiPlayer(bool singleInst) -{ - midiFile=NULL;resumed=false;singleInstance=singleInst; - settings=NULL;synth=NULL;adriver=NULL;waitvoice=true; -#ifdef _WIN32 - QueryPerformanceFrequency((LARGE_INTEGER*)&pf); -#endif -} -CMidiPlayer::~CMidiPlayer() -{ - if(singleInstance)fluidDeinitialize(); -} -void CMidiPlayer::playerPanic(bool reset) -{ - if(reset)for(int i=0;i<16;++i) - { - fluid_synth_pitch_bend(synth,i,8192); - fluid_synth_cc(synth,i,7,100); - fluid_synth_cc(synth,i,10,64); - fluid_synth_cc(synth,i,11,127); - } - for(int i=0;i<16;++i)fluid_synth_all_notes_off(synth,i); -} -bool CMidiPlayer::playerLoadFile(const char* fn) -{ - midiFile=new CMidiFile(fn); - if(!midiFile->isValid())return false; - divs=midiFile->getDivision(); - fileTimer1Pass(); - fileTimer2Pass(); - return true; -} -void CMidiPlayer::playerInit() -{ - ctempo=0x7A120;ctsn=4;ctsd=4;cks=0;dpt=ctempo*1000/divs; - tceptr=0;tcstop=0;tcpaused=0;finished=0;mute=solo=0; - sendSysEx=true;rpnid=rpnval=-1; - if(!singleInstance)fluidPreInitialize(); -} -void CMidiPlayer::playerDeinit() -{ - tceptr=0;tcstop=1;tcpaused=0; - delete midiFile;midiFile=NULL; - if(!singleInstance)fluidDeinitialize(); -} -void CMidiPlayer::playerThread() -{ - playEvents(); -} - -void CMidiPlayer::rendererLoadFile(const char* ofn) -{ - settings=new_fluid_settings(); - fluid_settings_setstr(settings,"audio.file.name",ofn); -} -void CMidiPlayer::rendererInit(const char* fn) -{ - finished=0; - synth=new_fluid_synth(settings); - player=new_fluid_player(synth); - fluid_player_add(player,fn); -} -void CMidiPlayer::rendererThread() -{ - fluid_file_renderer_t* renderer=new_fluid_file_renderer(synth); - fluid_player_play(player); - while(fluid_player_get_status(player)==FLUID_PLAYER_PLAYING) - if(fluid_file_renderer_process_block(renderer)!=FLUID_OK)break; - delete_fluid_file_renderer(renderer); - finished=1; -} -void CMidiPlayer::rendererDeinit() -{ - delete_fluid_player(player); - delete_fluid_synth(synth); - delete_fluid_settings(settings); - player=NULL;synth=NULL;settings=NULL; -} - -void CMidiPlayer::sendSysX(bool send){sendSysEx=send;} -uint32_t CMidiPlayer::getStamp(int id){return stamps[id];} -uint32_t CMidiPlayer::getTCeptr(){return tceptr;} -void CMidiPlayer::setTCeptr(uint32_t ep,uint32_t st) -{ - resumed=true; - if(ep==midiFile->getEventCount())tcstop=1;else tceptr=ep; - for(int i=0;i<16;++i) - { - for(int j=0;j<120;++j)fluid_synth_cc(synth,i,j,ccstamps[st][i][j]); - fluid_synth_program_change(synth,i,ccstamps[st][i][128]); - //fluid_synth_pitch_bend(synth,i,ccstamps[st][i][130]); - dpt=ccstamps[st][0][131];ctempo=dpt*divs/1000; - ctsn=ccstamps[st][0][132]>>24;ctsd=1<<((ccstamps[st][0][132]>>16)&0xFF); - cks=ccstamps[st][0][133]; - } -} -double CMidiPlayer::getFtime(){return ftime;} -void CMidiPlayer::getCurrentTimeSignature(int *n,int *d){*n=ctsn;*d=ctsd;} -void CMidiPlayer::getCurrentKeySignature(int *ks){*ks=cks;} -uint32_t CMidiPlayer::getFileNoteCount(){return midiFile?midiFile->getNoteCount():0;} -uint32_t CMidiPlayer::getFileStandard(){return midiFile?midiFile->getStandard():0;} -const char* CMidiPlayer::getTitle(){return midiFile?midiFile->getTitle():"";} -const char* CMidiPlayer::getCopyright(){return midiFile?midiFile->getCopyright():"";} -double CMidiPlayer::getTempo(){return 60./(ctempo/1e6)/**ctsd/4.*/;} -uint32_t CMidiPlayer::getTCpaused(){return tcpaused;} -void CMidiPlayer::setTCpaused(uint32_t ps){tcpaused=ps;} -uint32_t CMidiPlayer::isFinished(){return finished;} -void CMidiPlayer::setResumed(){resumed=true;} -void CMidiPlayer::setWaitVoice(bool wv){waitvoice=wv;} -void CMidiPlayer::setGain(double gain){if(settings)fluid_settings_setnum(settings,"synth.gain",gain);} -int CMidiPlayer::getPolyphone(){return synth?fluid_synth_get_active_voice_count(synth):0;} -int CMidiPlayer::getMaxPolyphone(){return synth?fluid_synth_get_polyphony(synth):0;} -void CMidiPlayer::setMaxPolyphone(int p){if(synth)fluid_synth_set_polyphony(synth,p);} - -void CMidiPlayer::getChannelPreset(int ch,int *b,int *p,char *name) -{ - if(!synth)return(void)(b=0,p=0,strcpy(name,"")); - fluid_synth_channel_info_t info; - fluid_synth_get_channel_info(synth,ch,&info); - *b=info.bank;*p=info.program; - strcpy(name,info.name); -} -void CMidiPlayer::setChannelPreset(int ch,int b,int p) -{ - if(!synth)return; - fluid_synth_bank_select(synth,ch,b); - fluid_synth_program_change(synth,ch,p); -} -//16MSB..LSB1 -void CMidiPlayer::setBit(uint16_t &n, uint16_t bn, uint16_t b) -{n^=(-b^n)&(1< -#include -#include -#include -struct SEvent -{ - uint32_t iid,time,p1,p2; - uint8_t type; - char *str; - SEvent(){time=p1=p2=0;type=0;str=NULL;} - SEvent(uint32_t _iid,uint32_t _t,char _tp,uint32_t _p1,uint32_t _p2,const char* s=NULL) - { - iid=_iid;time=_t;type=_tp; - p1=_p1;p2=_p2; - if(s){str=new char[strlen(s)+2];strcpy(str,s);}else str=NULL; - } -}; -class CMidiFile -{ - private: - SEvent *eventList[10000000]; - char *title,*copyright; - uint32_t eventc,std;//standard 0=? 1=GM 2=GM2 3=GS 4=XG - uint32_t fmt,trk,divs; - FILE *f; - int byteread,valid; - uint32_t notes,curt,curid; - - void error(int fatal,const char* format,...); - uint32_t readSW(); - uint32_t readDW(); - uint32_t readVL(); - int eventReader(); - void trackChunkReader(); - void headerChunkReader(); - int chunkReader(int hdrXp); - public: - CMidiFile(const char* fn); - ~CMidiFile(); - const SEvent* getEvent(uint32_t id); - uint32_t getEventCount(); - uint32_t getDivision(); - uint32_t getNoteCount(); - uint32_t getStandard(); - const char* getTitle(); - const char* getCopyright(); - bool isValid(); -}; -class CMidiPlayer -{ - private: - CMidiFile *midiFile; - uint32_t stamps[101]; - uint32_t ccstamps[101][16][135],ccc[16][135]; - //0..127:cc 128:pc 129:cp 130:pb 131:tempo 132:ts 133:ks 134:pbr - int32_t rpnid,rpnval; - uint16_t mute,solo; - double ftime; - bool sendSysEx,singleInstance,waitvoice; - fluid_settings_t* settings; - fluid_synth_t* synth; - fluid_audio_driver_t* adriver; - fluid_player_t* player; - uint32_t ctempo,ctsn,ctsd,dpt,divs,cks; - //raw tempo, timesig num., timesig den., delay per tick, division, keysig - //thread control - uint32_t tceptr,tcpaused,tcstop; - uint32_t finished,resumed; - - void setBit(uint16_t &n,uint16_t bn,uint16_t b); - void processEvent(const SEvent *e); - void processEventStub(const SEvent *e); - void playEvents(); - void fileTimer1Pass(); - void fileTimer2Pass(); - public: - CMidiPlayer(bool singleInst=false); - ~CMidiPlayer(); - bool playerLoadFile(const char* fn); - void playerInit(); - void fluidPreInitialize(); - void fluidInitialize(); - void fluidDeinitialize(); - void playerDeinit(); - void playerThread(); - void playerPanic(bool reset=false); - - void rendererLoadFile(const char* ofn); - void rendererInit(const char *fn); - void rendererThread(); - void rendererDeinit(); - - //playing control methods - uint32_t getStamp(int id); - uint32_t getTCeptr(); - void setTCeptr(uint32_t ep,uint32_t st); - uint32_t getTCpaused(); - void setTCpaused(uint32_t ps); - uint32_t isFinished(); - void setResumed(); - void setWaitVoice(bool wv); - - double getFtime(); - void getCurrentTimeSignature(int *n,int *d); - void getCurrentKeySignature(int *ks); - uint32_t getFileNoteCount(); - uint32_t getFileStandard(); - double getTempo(); - const char* getTitle(); - const char* getCopyright(); - - void setGain(double gain); - void sendSysX(bool send); - int getPolyphone(); - int getMaxPolyphone(); - void setMaxPolyphone(int p); - - 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); - int getCC(int ch,int id); - void setCC(int ch,int id,int val); - void getReverbPara(double *r,double *d,double *w,double *l); - void setReverbPara(int e,double r,double d,double w,double l); - void getChorusPara(int *fb,double *l,double *r,double *d,int *type); - void setChorusPara(int e,int fb,double l,double r,double d,int type); - - fluid_settings_t* getFluidSettings(); - void pushSoundFont(const char* sf); - int getSFCount(); - fluid_sfont_t* getSFPtr(int sfid); -}; -#endif diff --git a/qmpmidiread.cpp b/qmpmidiread.cpp deleted file mode 100644 index fd2e0d9..0000000 --- a/qmpmidiread.cpp +++ /dev/null @@ -1,239 +0,0 @@ -//CLI Midi file player based on libfluidsynth -//Midi file reading module -//Written by Chris Xiong, 2015 -#include -#include -#include -#include -#include -#include -#include "qmpmidiplay.hpp" -const char* GM1SysX={"\xF0\x7E\x7F\x09\x01\xF7"}; -const char* GM2SysX={"\xF0\x7E\x7F\x09\x03\xF7"}; -const char* GSSysEx={"\xF0\x41\x10\x42\x12\x40\x00\x7F\x00\x41\xF7"}; -const char* XGSysEx={"\xF0\x43\x10\x4C\x00\x00\x7E\x00\xF7"}; -bool cmp(SEvent *a,SEvent *b){return a->time-b->time?a->timetime:a->iidiid;} -void CMidiFile::error(int fatal,const char* format,...) -{ - va_list ap; - va_start(ap,format);vfprintf(stderr,format,ap);va_end(ap); - fprintf(stderr," at %#lx\n",ftell(f)); - if(fatal)throw 2; -} -uint32_t CMidiFile::readSW() -{ - byteread+=2; - uint32_t ret=0; - for(int i=0;i<2;++i){ret<<=8;ret|=((uint32_t)fgetc(f))&0xFF;} - return ret; -} -uint32_t CMidiFile::readDW() -{ - byteread+=4; - uint32_t ret=0; - for(int i=0;i<4;++i){ret<<=8;ret|=((uint32_t)fgetc(f))&0xFF;} - return ret; -} -uint32_t CMidiFile::readVL() -{ - uint32_t ret=0,t,c=0; - do - { - t=fgetc(f); - if(++c>4)error(1,"E: Variable length type overflow."); - ret<<=7;ret|=(t&0x7F); - }while(t&0x80); - byteread+=c; - return ret; -} -int CMidiFile::eventReader()//returns 0 if End of Track encountered -{ - uint32_t delta=readVL();curt+=delta; - char type=fgetc(f);++byteread;uint32_t p1,p2; - static char lasttype; -retry: - switch(type&0xF0) - { - case 0x80://Note Off - p1=fgetc(f);p2=fgetc(f);byteread+=2; - eventList[eventc++]=new SEvent(curid,curt,type,p1,p2); - break; - case 0x90://Note On - p1=fgetc(f);p2=fgetc(f);byteread+=2; - if(p2) - { - ++notes; - eventList[eventc++]=new SEvent(curid,curt,type,p1,p2); - } - else - eventList[eventc++]=new SEvent(curid,curt,(type&0x0F)|0x80,p1,p2); - break; - case 0xA0://Note Aftertouch - p1=fgetc(f);p2=fgetc(f);byteread+=2; - eventList[eventc++]=new SEvent(curid,curt,type,p1,p2); - break; - case 0xB0://Controller Change - p1=fgetc(f);p2=fgetc(f);byteread+=2; - eventList[eventc++]=new SEvent(curid,curt,type,p1,p2); - break; - case 0xC0://Patch Change - p1=fgetc(f);++byteread; - eventList[eventc++]=new SEvent(curid,curt,type,p1,0); - break; - case 0xD0://Channel Aftertouch - p1=fgetc(f);++byteread; - eventList[eventc++]=new SEvent(curid,curt,type,p1,0); - break; - case 0xE0://Pitch wheel - p1=fgetc(f);p2=fgetc(f);byteread+=2; - eventList[eventc++]=new SEvent(curid,curt,type,(p1|(p2<<7))&0x3FFF,0); - break; - case 0xF0: - if((type&0x0F)==0x0F)//Meta Event - { - char metatype=fgetc(f);++byteread; - switch(metatype) - { - case 0x00://Sequence Number - fgetc(f);fgetc(f);fgetc(f); - byteread+=3; - break; - case 0x20://Channel Prefix - fgetc(f);fgetc(f);byteread+=2; - break; - case 0x2F://End of Track - fgetc(f);++byteread; - return 0; - break; - case 0x51://Set Tempo - p1=readDW();p1&=0x00FFFFFF; - eventList[eventc++]=new SEvent(curid,curt,type,metatype,p1); - break; - case 0x54://SMTPE offset, not handled. - fgetc(f);fgetc(f);fgetc(f); - fgetc(f);fgetc(f);fgetc(f); - byteread+=6; - break; - case 0x58://Time signature - fgetc(f);++byteread; - p1=readDW(); - eventList[eventc++]=new SEvent(curid,curt,type,metatype,p1); - break; - case 0x59://Key signature - fgetc(f);++byteread; - p1=readSW(); - eventList[eventc++]=new SEvent(curid,curt,type,metatype,p1); - break; - case 0x01:case 0x02:case 0x03: - case 0x04:case 0x05:case 0x06: - case 0x07:case 0x7F:default://text-like meta - { - uint32_t len=readVL(),c;char* str=NULL; - if(len<=1024&&len>0)str=new char[len+8]; - for(c=0;c0)delete[] str; - } - } - } - else if((type&0x0F)==0x00||(type&0x0F)==0x07)//SysEx - { - uint32_t len=readVL(),c;char* str=NULL; - str=new char[len+8]; - if((type&0x0F)==0x00) - { - str[0]=0xF0;++len; - for(c=1;cchnklen) - { - error(1,"E: Read past end of track."); - }*/ -} -void CMidiFile::headerChunkReader() -{ - int chnklen=readDW();byteread=0; - if(chnklen<6)error(1,"E: Header chunk too short."); - if(chnklen>6)error(0,"W: Header chunk length longer than expected. Ignoring extra bytes."); - fmt=readSW();trk=readSW();divs=readSW(); - if(divs&0x8000)error(1,"E: SMTPE format is not supported."); - for(;byteread0;--chnklen)fgetc(f);return 0; - } - else return trackChunkReader(),1; -} -CMidiFile::CMidiFile(const char* fn) -{ - title=copyright=NULL;notes=eventc=0;std=0;valid=1; - try - { - if(!(f=fopen(fn,"rb")))throw (fprintf(stderr,"E: file %s doesn't exist!\n",fn),2); - chunkReader(1); - for(uint32_t i=0;i -#include -#include -#include -#include -#include -#include -#include -#include "qmpplistwindow.hpp" -#include "ui_qmpplistwindow.h" -#include "qmpmainwindow.hpp" - -qmpPlistWindow::qmpPlistWindow(QWidget *parent) : - QDialog(parent), - ui(new Ui::qmpPlistWindow) -{ - ui->setupUi(this); - connect(this,SIGNAL(dialogClosing()),parent,SLOT(dialogClosed())); - connect(this,SIGNAL(selectionChanging()),parent,SLOT(selectionChanged())); - repeat=0;shuffle=0; - if(qmpSettingsWindow::getSettingsIntf()->value("Behavior/RestorePlaylist","").toInt()) - { - QSettings* plist=new QSettings(QDir::homePath()+QString("/.config/qmpplist"), - QSettings::IniFormat); - int fc=plist->value("Playlist/FileCount",0).toInt(); - ui->lwFiles->clear();for(int i=1;i<=fc;++i) - ui->lwFiles->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(); - switch(shuffle) - { - case 1: - ui->pbShuffle->setIcon(QIcon(":/img/shuffle.png")); - ui->pbShuffle->setText("Shuffle On"); - break; - case 0: - default: - ui->pbShuffle->setIcon(QIcon(":/img/shuffle-off.png")); - ui->pbShuffle->setText("Shuffle Off"); - break; - } - switch(repeat) - { - case 0: - ui->pbRepeat->setIcon(QIcon(":/img/repeat-non.png")); - ui->pbRepeat->setText("Repeat Off"); - break; - case 1: - ui->pbRepeat->setIcon(QIcon(":/img/repeat-one.png")); - ui->pbRepeat->setText("Repeat One"); - break; - case 2: - ui->pbRepeat->setIcon(QIcon(":/img/repeat-all.png")); - ui->pbRepeat->setText("Repeat All"); - break; - } - delete plist; - } -} - -qmpPlistWindow::~qmpPlistWindow() -{ - delete ui; -} - -void qmpPlistWindow::showEvent(QShowEvent *event) -{ - if(qmpSettingsWindow::getSettingsIntf()->value("Behavior/DialogStatus","").toInt()) - { - qmpSettingsWindow::getSettingsIntf()->setValue("DialogStatus/PListWShown",1); - } - event->accept(); -} - -void qmpPlistWindow::closeEvent(QCloseEvent *event) -{ - setVisible(false); - if(!qmpMainWindow::getInstance()->isFinalizing()&&qmpSettingsWindow::getSettingsIntf()->value("Behavior/DialogStatus","").toInt()) - { - qmpSettingsWindow::getSettingsIntf()->setValue("DialogStatus/PListWShown",0); - } - if(qmpMainWindow::getInstance()->isFinalizing()&&qmpSettingsWindow::getSettingsIntf()->value("Behavior/RestorePlaylist","").toInt()) - { - QSettings* plist=new QSettings(QDir::homePath()+QString("/.config/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/Repeat",repeat); - plist->setValue("Playlist/Shuffle",shuffle); - plist->sync(); - delete plist; - } - emit dialogClosing(); - event->accept(); -} - -void qmpPlistWindow::moveEvent(QMoveEvent *event) -{ - if(qmpSettingsWindow::getSettingsIntf()->value("Behavior/DialogStatus","").toInt()) - { - qmpSettingsWindow::getSettingsIntf()->setValue("DialogStatus/PListW",event->pos()); - } -} - -void qmpPlistWindow::dropEvent(QDropEvent *event) -{ - QList l=event->mimeData()->urls(); - QStringList sl; - for(int i=0;imimeData()->hasFormat("application/x-midi")) - event->acceptProposedAction(); -} - -void qmpPlistWindow::emptyList() -{ - ui->lwFiles->clear(); -} -void qmpPlistWindow::insertItem(QString i) -{ - ui->lwFiles->addItem(new QListWidgetItem(i)); -} -void qmpPlistWindow::insertItems(QStringList il) -{ - ui->lwFiles->addItems(il); -} - -void 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)"); - else - sl=QFileDialog::getOpenFileNames(this,"Add File","","Midi files (*.mid *.midi)"); - if(sl.empty())return; - for(int i=0;ilwFiles->addItem(new QListWidgetItem(sl.at(i))); - } - if(qmpSettingsWindow::getSettingsIntf()->value("Behavior/DialogStatus","").toInt()) - qmpSettingsWindow::getSettingsIntf()->setValue("DialogStatus/FileDialogPath", - QUrl(sl.at(0)).toString(QUrl::RemoveFilename)); -} - -void qmpPlistWindow::on_pbAddFolder_clicked() -{ - QDirIterator di(QFileDialog::getExistingDirectory(this,"Add Folder")); - while(di.hasNext()) - { - QString c=di.next(); - if((c.endsWith(".mid")||c.endsWith(".midi"))&&fluid_is_midifile(c.toStdString().c_str())) - ui->lwFiles->addItem(new QListWidgetItem(c)); - } -} - -void qmpPlistWindow::on_pbRemove_clicked() -{ - QList sl=ui->lwFiles->selectedItems(); - for(int i=0;ilwFiles->removeItemWidget(sl.at(i)); - delete sl.at(i); - } -} - -void qmpPlistWindow::on_pbClear_clicked() -{ - while(ui->lwFiles->count()>0) - { - QListWidgetItem *d=ui->lwFiles->item(0); - ui->lwFiles->removeItemWidget(d); - delete d; - } -} - -void qmpPlistWindow::on_pbRepeat_clicked() -{ - ++repeat;repeat%=3; - switch(repeat) - { - case 0: - ui->pbRepeat->setIcon(QIcon(":/img/repeat-non.png")); - ui->pbRepeat->setText("Repeat Off"); - break; - case 1: - ui->pbRepeat->setIcon(QIcon(":/img/repeat-one.png")); - ui->pbRepeat->setText("Repeat One"); - break; - case 2: - ui->pbRepeat->setIcon(QIcon(":/img/repeat-all.png")); - ui->pbRepeat->setText("Repeat All"); - break; - } -} - -void qmpPlistWindow::on_pbShuffle_clicked() -{ - shuffle=1-shuffle; - switch(shuffle) - { - case 1: - ui->pbShuffle->setIcon(QIcon(":/img/shuffle.png")); - ui->pbShuffle->setText("Shuffle On"); - break; - case 0: - default: - ui->pbShuffle->setIcon(QIcon(":/img/shuffle-off.png")); - ui->pbShuffle->setText("Shuffle Off"); - break; - } -} - -QString qmpPlistWindow::getFirstItem() -{ - if(ui->lwFiles->count()==0)return QString(); - int id=0; - if(shuffle)id=rand()%ui->lwFiles->count(); - ui->lwFiles->setCurrentRow(id); - return ui->lwFiles->item(id)->text(); -} -QString qmpPlistWindow::getNextItem() -{ - if(ui->lwFiles->count()==0)return QString(); - if(repeat==1)return ui->lwFiles->item(ui->lwFiles->currentRow())->text(); - int id=ui->lwFiles->currentRow();++id;id%=ui->lwFiles->count(); - if(shuffle)id=rand()%ui->lwFiles->count(); - ui->lwFiles->setCurrentRow(id); - return ui->lwFiles->item(id)->text(); -} -QString qmpPlistWindow::getPrevItem() -{ - if(ui->lwFiles->count()==0)return QString(); - if(repeat==1)return ui->lwFiles->item(ui->lwFiles->currentRow())->text(); - int id=ui->lwFiles->currentRow();--id; - id<0?id+=ui->lwFiles->count():0; - if(shuffle)id=rand()%ui->lwFiles->count(); - ui->lwFiles->setCurrentRow(id); - return ui->lwFiles->item(id)->text(); -} -QString qmpPlistWindow::getSelectedItem() -{ - if(ui->lwFiles->count()==0)return QString(); - return ui->lwFiles->item(ui->lwFiles->currentRow())->text(); -} -int qmpPlistWindow::getRepeat(){return repeat;} - -void qmpPlistWindow::on_lwFiles_itemDoubleClicked() -{ - emit selectionChanging(); -} - -void qmpPlistWindow::on_pbSave_clicked() -{ - QSettings* plist=new QSettings(QFileDialog::getSaveFileName(this,"Save playlist",""), - 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/Repeat",repeat); - plist->setValue("Playlist/Shuffle",shuffle); - plist->sync(); - delete plist; -} - -void qmpPlistWindow::on_pbLoad_clicked() -{ - QSettings* plist=new QSettings(QFileDialog::getOpenFileName(this,"Load playlist",""), - QSettings::IniFormat); - int fc=plist->value("Playlist/FileCount",0).toInt(); - if(!fc)return; - ui->lwFiles->clear();for(int i=1;i<=fc;++i) - ui->lwFiles->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(); - switch(shuffle) - { - case 1: - ui->pbShuffle->setIcon(QIcon(":/img/shuffle.png")); - ui->pbShuffle->setText("Shuffle On"); - break; - case 0: - default: - ui->pbShuffle->setIcon(QIcon(":/img/shuffle-off.png")); - ui->pbShuffle->setText("Shuffle Off"); - break; - } - switch(repeat) - { - case 0: - ui->pbRepeat->setIcon(QIcon(":/img/repeat-non.png")); - ui->pbRepeat->setText("Repeat Off"); - break; - case 1: - ui->pbRepeat->setIcon(QIcon(":/img/repeat-one.png")); - ui->pbRepeat->setText("Repeat One"); - break; - case 2: - ui->pbRepeat->setIcon(QIcon(":/img/repeat-all.png")); - ui->pbRepeat->setText("Repeat All"); - break; - } - delete plist; -} diff --git a/qmpplistwindow.hpp b/qmpplistwindow.hpp deleted file mode 100644 index 6ceeb60..0000000 --- a/qmpplistwindow.hpp +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef QMPPLISTWINDOW_H -#define QMPPLISTWINDOW_H - -#include -#include -#include -#include -#include -#include -#include - -namespace Ui { - class qmpPlistWindow; -} - -class qmpPlistWindow : public QDialog -{ - Q_OBJECT - - public: - explicit qmpPlistWindow(QWidget *parent=0); - ~qmpPlistWindow(); - void showEvent(QShowEvent *event); - void closeEvent(QCloseEvent *event); - void moveEvent(QMoveEvent *event); - void dropEvent(QDropEvent *event); - void dragEnterEvent(QDragEnterEvent *event); - int getRepeat(); - QString getFirstItem(); - QString getNextItem(); - QString getPrevItem(); - QString getSelectedItem(); - void emptyList(); - void insertItem(QString i); - void insertItems(QStringList il); - signals: - void dialogClosing(); - void selectionChanging(); - - public slots: - void on_pbAdd_clicked(); - private slots: - void on_pbAddFolder_clicked(); - void on_pbRemove_clicked(); - void on_pbClear_clicked(); - void on_pbRepeat_clicked(); - void on_pbShuffle_clicked(); - void on_lwFiles_itemDoubleClicked(); - void on_pbSave_clicked(); - void on_pbLoad_clicked(); - - private: - Ui::qmpPlistWindow *ui; - int shuffle,repeat;//rep 0=off 1=one 2=all -}; - -#endif // QMPPLISTWINDOW_H diff --git a/qmpplistwindow.ui b/qmpplistwindow.ui deleted file mode 100644 index 99124df..0000000 --- a/qmpplistwindow.ui +++ /dev/null @@ -1,263 +0,0 @@ - - - qmpPlistWindow - - - - 0 - 0 - 530 - 321 - - - - - 530 - 321 - - - - - 530 - 321 - - - - true - - - Playlist - - - - - 10 - 280 - 121 - 36 - - - - text-align:left - - - Add - - - - :/img/add.png:/img/add.png - - - - 32 - 32 - - - - - - - 140 - 280 - 121 - 36 - - - - text-align:left - - - Add Folder - - - - :/img/addfolder.png:/img/addfolder.png - - - - 32 - 32 - - - - - - - 270 - 240 - 121 - 36 - - - - text-align:left - - - Repeat Off - - - - :/img/repeat-non.png:/img/repeat-non.png - - - - 32 - 32 - - - - - - - 400 - 240 - 121 - 36 - - - - text-align:left - - - Shuffle Off - - - - :/img/shuffle-off.png:/img/shuffle-off.png - - - - 32 - 32 - - - - - - - 10 - 240 - 121 - 36 - - - - text-align:left - - - Save - - - - :/img/save.png:/img/save.png - - - - 32 - 32 - - - - - - - 140 - 240 - 121 - 36 - - - - text-align:left - - - Load - - - - :/img/load.png:/img/load.png - - - - 32 - 32 - - - - - - - 270 - 280 - 121 - 36 - - - - text-align:left - - - Remove - - - - :/img/remove.png:/img/remove.png - - - - 32 - 32 - - - - - - - 400 - 280 - 121 - 36 - - - - text-align:left - - - Clear - - - - :/img/clear.png:/img/clear.png - - - - 32 - 32 - - - - - - - 10 - 10 - 511 - 221 - - - - false - - - true - - - QAbstractItemView::InternalMove - - - - - - - - diff --git a/qmppresetselect.cpp b/qmppresetselect.cpp deleted file mode 100644 index be589c5..0000000 --- a/qmppresetselect.cpp +++ /dev/null @@ -1,99 +0,0 @@ -#include -#include "qmppresetselect.hpp" -#include "ui_qmppresetselect.h" -#include "qmpmainwindow.hpp" - -qmpPresetSelector::qmpPresetSelector(QWidget *parent) : - QDialog(parent), - ui(new Ui::qmpPresetSelector) -{ - ui->setupUi(this); -} - -qmpPresetSelector::~qmpPresetSelector() -{ - delete ui; -} - -void qmpPresetSelector::showEvent(QShowEvent *e) -{ - memset(presets,0,sizeof(presets)); - CMidiPlayer *plyr=qmpMainWindow::getInstance()->getPlayer(); - if(!plyr->getSFCount())return e->ignore(); - int sfc=plyr->getSFCount(); - for(int i=sfc-1;i>=0;--i) - { - fluid_sfont_t* psf=plyr->getSFPtr(i); - fluid_preset_t preset; - psf->iteration_start(psf); - while(psf->iteration_next(psf,&preset)) - strcpy(presets[preset.get_banknum(&preset)][preset.get_num(&preset)],preset.get_name(&preset)); - } - 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->getSFCount())return; - ch=chid;int b=0,p=0,r;char name[64]; - sprintf(name,"Preset Selection - Channel #%d",ch+1); - setWindowTitle(name); - plyr->getChannelPreset(chid,&b,&p,name); - for(int i=0;ilwBankSelect->count();++i) - { - sscanf(ui->lwBankSelect->item(i)->text().toStdString().c_str(),"%d",&r); - if(r==b){ui->lwBankSelect->setCurrentRow(i);break;} - } - r=0; - ui->lwPresetSelect->clear(); - for(int i=0,cr=0;i<128;++i) - if(strlen(presets[b][i])) - { - sprintf(name,"%d %s",i,presets[b][i]); - if(i==p)r=cr; - ui->lwPresetSelect->addItem(name); - cr++; - } - ui->lwPresetSelect->setCurrentRow(r); -} - -void qmpPresetSelector::on_pbCancel_clicked() -{ - close(); -} - -void qmpPresetSelector::on_pbOk_clicked() -{ - CMidiPlayer *plyr=qmpMainWindow::getInstance()->getPlayer(); - int b,p;sscanf(ui->lwBankSelect->currentItem()->text().toStdString().c_str(),"%d",&b); - sscanf(ui->lwPresetSelect->currentItem()->text().toStdString().c_str(),"%d",&p); - plyr->setChannelPreset(ch,b,p); - close(); -} - -void qmpPresetSelector::on_lwPresetSelect_itemDoubleClicked() -{ - on_pbOk_clicked(); -} - -void qmpPresetSelector::on_lwBankSelect_currentRowChanged() -{ - ui->lwPresetSelect->clear(); - if(!ui->lwBankSelect->currentItem())return; - char name[30];int b; - sscanf(ui->lwBankSelect->currentItem()->text().toStdString().c_str(),"%d",&b); - for(int i=0;i<128;++i) - if(strlen(presets[b][i])) - { - sprintf(name,"%d %s",i,presets[b][i]); - ui->lwPresetSelect->addItem(name); - } -} diff --git a/qmppresetselect.hpp b/qmppresetselect.hpp deleted file mode 100644 index 54f5764..0000000 --- a/qmppresetselect.hpp +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef QMPPRESETSELECT_H -#define QMPPRESETSELECT_H - -#include -#include - -namespace Ui { - class qmpPresetSelector; -} - -class qmpPresetSelector:public QDialog -{ - Q_OBJECT - - public: - explicit qmpPresetSelector(QWidget *parent = 0); - ~qmpPresetSelector(); - void showEvent(QShowEvent* e); - void setupWindow(int chid); - - private slots: - void on_pbCancel_clicked(); - - void on_pbOk_clicked(); - - void on_lwBankSelect_currentRowChanged(); - - void on_lwPresetSelect_itemDoubleClicked(); - - private: - Ui::qmpPresetSelector *ui; - char presets[129][128][24]; - int ch; -}; - -#endif // QMPPRESETSELECT_H diff --git a/qmppresetselect.ui b/qmppresetselect.ui deleted file mode 100644 index f18600d..0000000 --- a/qmppresetselect.ui +++ /dev/null @@ -1,106 +0,0 @@ - - - qmpPresetSelector - - - - 0 - 0 - 404 - 300 - - - - - 404 - 300 - - - - - 404 - 300 - - - - Preset Selection - - - true - - - - - 10 - 30 - 71 - 221 - - - - - - - 90 - 30 - 301 - 221 - - - - - - - 10 - 10 - 66 - 20 - - - - Bank - - - - - - 90 - 10 - 66 - 20 - - - - Preset - - - - - - 300 - 260 - 97 - 36 - - - - OK - - - - - - 190 - 260 - 97 - 36 - - - - Cancel - - - - - - diff --git a/qmpsettingswindow.cpp b/qmpsettingswindow.cpp deleted file mode 100644 index c2e31a2..0000000 --- a/qmpsettingswindow.cpp +++ /dev/null @@ -1,289 +0,0 @@ -#include -#include -#include "qmpsettingswindow.hpp" -#include "ui_qmpsettingswindow.h" -#include "qmpmainwindow.hpp" - -QSettings *qmpSettingsWindow::settings=NULL; - -void qmpFluidForEachOpt(void* data,char* /*name*/,char* option) -{ - QComboBox *pcb=(QComboBox*)data; - pcb->addItem(option); -} - -qmpSettingsWindow::qmpSettingsWindow(QWidget *parent) : - QDialog(parent), - ui(new Ui::qmpSettingsWindow) -{ - ui->setupUi(this); - connect(this,SIGNAL(dialogClosing()),parent,SLOT(dialogClosed())); - settings=new QSettings(QDir::homePath()+QString("/.config/qmprc"),QSettings::IniFormat); - settingsInit(); -} - -qmpSettingsWindow::~qmpSettingsWindow() -{ - delete settings; - delete ui; -} - -void qmpSettingsWindow::closeEvent(QCloseEvent *event) -{ - setVisible(false); - settings->sync(); - emit dialogClosing(); - event->accept(); -} - -QListWidget* qmpSettingsWindow::getSFWidget(){return ui->lwSoundfont;} - -void qmpSettingsWindow::on_buttonBox_accepted() -{ - settingsUpdate(); - emit dialogClosing(); -} - -void qmpSettingsWindow::on_buttonBox_rejected() -{ - settingsInit(); - emit dialogClosing(); -} - -void qmpSettingsWindow::settingsInit() -{ - fluid_settings_t *fsettings=new_fluid_settings(); - - settings->setValue("Midi/DefaultOutput",settings->value("Midi/DefaultOutput","Internal FluidSynth")); - //this item is still a stub... - - 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 8192 -#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 - - selected=-1; - for(int i=0;icbBufCnt->count();++i) - if(ui->cbBufCnt->itemText(i).toInt()==settings->value("Audio/BufCnt",2).toInt()) - {selected=i;break;} - if(~selected)ui->cbBufCnt->setCurrentIndex(selected); - else if(settings->value("Audio/BufCnt",2).toInt()>=2&&settings->value("Audio/BufCnt",2).toInt()<=64) - ui->cbBufCnt->setCurrentText(settings->value("Audio/BufCnt",2).toString()); - else ui->cbBufCnt->setCurrentText("2"); - settings->setValue("Audio/BufCnt",ui->cbBufCnt->currentText().toInt()); - - 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","GS").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)); - - int sfc=settings->value("SoundFonts/SFCount",0).toInt(); - ui->lwSoundfont->clear();for(int i=1;i<=sfc;++i) - ui->lwSoundfont->addItem(settings->value("SoundFonts/SF"+QString::number(i),"").toString()); - settings->setValue("SoundFonts/SFCount",sfc); - - 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->sync(); - delete_fluid_settings(fsettings); -} - -void qmpSettingsWindow::settingsUpdate() -{ - settings->setValue("Midi/DefaultOutput",settings->value("Midi/DefaultOutput","Internal FluidSynth")); - //this item is still a stub... - - 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()); - - settings->setValue("SoundFonts/SFCount",ui->lwSoundfont->count()); - for(int i=0;ilwSoundfont->count();++i) - settings->setValue("SoundFonts/SF"+QString::number(i+1),ui->lwSoundfont->item(i)->text()); - - 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); - 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"); - } - - settings->setValue("Behavior/SingleInstance",ui->cbPersistentfs->isChecked()?1:0); - 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;ilwSoundfont->addItem(new QListWidgetItem(sl.at(i))); - } -} - -void qmpSettingsWindow::on_pbRemove_clicked() -{ - QList sl=ui->lwSoundfont->selectedItems(); - for(int i=0;ilwSoundfont->removeItemWidget(sl.at(i)); - delete sl.at(i); - } -} - -void qmpSettingsWindow::on_pbUp_clicked() -{ - int cid=ui->lwSoundfont->currentRow(); - QListWidgetItem *ci=ui->lwSoundfont->takeItem(cid); - ui->lwSoundfont->insertItem(cid-1,ci); - ui->lwSoundfont->setCurrentRow(cid-1); -} - -void qmpSettingsWindow::on_pbDown_clicked() -{ - int cid=ui->lwSoundfont->currentRow(); - QListWidgetItem *ci=ui->lwSoundfont->takeItem(cid); - ui->lwSoundfont->insertItem(cid+1,ci); - ui->lwSoundfont->setCurrentRow(cid+1); -} - -void qmpSettingsWindow::on_cbAutoBS_stateChanged() -{ - ui->lbBSMode->setText(ui->cbAutoBS->isChecked()?"Fallback bank select mode":"Bank select mode"); -} diff --git a/qmpsettingswindow.hpp b/qmpsettingswindow.hpp deleted file mode 100644 index c506de4..0000000 --- a/qmpsettingswindow.hpp +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef QMPSETTINGSWINDOW_H -#define QMPSETTINGSWINDOW_H - -#include -#include -#include -#include - -namespace Ui { - class qmpSettingsWindow; -} - -class qmpSettingsWindow:public QDialog -{ - Q_OBJECT - - public: - explicit qmpSettingsWindow(QWidget *parent=0); - ~qmpSettingsWindow(); - void closeEvent(QCloseEvent *event); - void settingsInit(); - QListWidget* getSFWidget(); - signals: - void dialogClosing(); - - private slots: - 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(); - - private: - Ui::qmpSettingsWindow *ui; - void settingsUpdate(); - static QSettings *settings; - public: static QSettings* getSettingsIntf(){return settings;} -}; - -#endif // QMPSETTINGSWINDOW_H diff --git a/qmpsettingswindow.ui b/qmpsettingswindow.ui deleted file mode 100644 index 330afa2..0000000 --- a/qmpsettingswindow.ui +++ /dev/null @@ -1,761 +0,0 @@ - - - qmpSettingsWindow - - - - 0 - 0 - 494 - 445 - - - - - 494 - 445 - - - - Settings - - - - - - 0 - - - - Midi - - - - - - - - - 0 - 0 - - - - Default Output Device - - - - - - - - 0 - 0 - - - - - Internal FluidSynth - - - - - - - - - - - 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 - - - - - - - - - - - Synth - - - - - - Audio Buffer Count - - - - - - - Audio Buffer Size - - - - - - - true - - - 1 - - - - 64 - - - - - 128 - - - - - 256 - - - - - 512 - - - - - 1024 - - - - - 2048 - - - - - 4096 - - - - - 8192 - - - - - - - - Audio Frequency - - - - - - - true - - - - 2 - - - - - 4 - - - - - 8 - - - - - 16 - - - - - 32 - - - - - 64 - - - - - - - - Audio Driver - - - - - - - - 16bits - - - - - float - - - - - - - - - - - 2 - - - - 22050 - - - - - 44100 - - - - - 48000 - - - - - 96000 - - - - - - - - Audio 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 - - - - - - - - - - - - - :/img/add.png:/img/add.png - - - - 24 - 24 - - - - - - - - - - - - :/img/remove.png:/img/remove.png - - - - 24 - 24 - - - - - - - - - - - - :/img/up.png:/img/up.png - - - - 24 - 24 - - - - - - - - - - - - :/img/down.png:/img/down.png - - - - 24 - 24 - - - - - - - - - - - Behavior - - - - - - Restore last playlist on startup - - - - - - - Load files in the same folder - - - - - - - Save dialog status - - - - - - - Save parameters in effects window - - - - - - - Persistent fluidsynth instance - - - - - - - - - Visualization Mode - - - - - - - - - - - - - - View distance - - - - - - - Qt::Horizontal - - - QSizePolicy::Expanding - - - - 50 - 20 - - - - - - - - - 60 - 0 - - - - Qt::Horizontal - - - - - - - - - - - - - - Note stretch - - - - - - - Qt::Horizontal - - - QSizePolicy::Expanding - - - - 60 - 20 - - - - - - - - - 60 - 0 - - - - Qt::Horizontal - - - - - - - - - - - - - - Fog Start - - - - - - - Qt::Horizontal - - - QSizePolicy::Expanding - - - - 82 - 20 - - - - - - - - - 60 - 0 - - - - Qt::Horizontal - - - - - - - - - - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - - - buttonBox - accepted() - qmpSettingsWindow - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - qmpSettingsWindow - reject() - - - 316 - 260 - - - 286 - 274 - - - - - diff --git a/resources.qrc b/resources.qrc deleted file mode 100644 index 2eb232c..0000000 --- a/resources.qrc +++ /dev/null @@ -1,36 +0,0 @@ - - - img/add.png - img/list.png - img/addfolder.png - img/channel.png - img/prev.png - img/qmidiplyr.png - img/remove.png - img/clear.png - img/down.png - img/effects.png - img/repeat-all.png - img/repeat-base.png - img/repeat-non.png - img/load.png - img/next.png - img/repeat-one.png - img/save.png - img/settings.png - img/pause.png - img/play.png - img/shuffle-off.png - img/shuffle.png - img/stop.png - img/up.png - img/visualization.png - img/mainw.png - img/chanw.png - doc/index.html - doc/version.html - doc/license.html - doc/mainwindow.html - doc/channeldialog.html - - -- cgit v1.2.3