diff options
author | Chris Xiong <chirs241097@gmail.com> | 2016-04-25 23:46:17 +0800 |
---|---|---|
committer | Chris Xiong <chirs241097@gmail.com> | 2016-04-25 23:46:17 +0800 |
commit | 4ffde0ad55d041229793ca4457123bcbcbf8e0c0 (patch) | |
tree | 9457cee58f3a1f35ebe63de79c6811b1c16e36dc /visualization/qmpvisualization.cpp | |
parent | 800a0417e9ed175f220c472842a283202c77060b (diff) | |
download | QMidiPlayer-4ffde0ad55d041229793ca4457123bcbcbf8e0c0.tar.xz |
Plugin API now works correctly. Port old visualization code.
Diffstat (limited to 'visualization/qmpvisualization.cpp')
-rw-r--r-- | visualization/qmpvisualization.cpp | 214 |
1 files changed, 203 insertions, 11 deletions
diff --git a/visualization/qmpvisualization.cpp b/visualization/qmpvisualization.cpp index e8bb9fb..2d0b494 100644 --- a/visualization/qmpvisualization.cpp +++ b/visualization/qmpvisualization.cpp @@ -1,34 +1,218 @@ #include <cstdio> +#include <cstdlib> +#include <cstring> +#include <cmath> #include "qmpvisualization.hpp" +const int viewdist=100; +const int notestretch=100;//length of quarter note +const int minnotelength=100; +DWORD chcolors[]={0XFFFF0000,0XFFFF8000,0XFFFFBF00,0XFFFFFF00, + 0XFFBFFF00,0XFF80FF00,0XFF00FF00,0XFF00FFBF, + 0XFF00FFFF,0XFF333333,0XFF00BFFF,0XFF007FFF, + 0XFF0000FF,0XFF7F00FF,0XFFBF00FF,0XFFFF00BF}; + void CTestCallBack::callBack(void *callerdata,void *) { - if(par->c<3) + SEventCallBackData* cbd=(SEventCallBackData*)callerdata; + switch(cbd->type&0xF0) { - SEventCallBackData* cbd=(SEventCallBackData*)callerdata; - printf("type %#x p1 %d p2 %d\n",cbd->type,cbd->p1,cbd->p2); + case 0x80: + par->pushNoteOff(cbd->time,cbd->type&0x0F,cbd->p1); + break; + case 0x90: + par->pushNoteOn(cbd->time,cbd->type&0x0F,cbd->p1,cbd->p2); + break; } } +void qmpVisualization::show() +{ + sm=smGetInterface(SMELT_APILEVEL); + sm->smVidMode(800,600,true); + sm->smUpdateFunc(h); + sm->smWinTitle("A Stupid Midi Visualization"); + sm->smSetFPS(FPS_VSYNC); + sm->smNoSuspend(true); + sm->smInit(); + sm->smTextureOpt(TPOT_POT,TFLT_LINEAR); + chequer=sm->smTextureLoad("chequerboard.png"); + tdscn=sm->smTargetCreate(800,600); + if(!font.loadTTF("/usr/share/fonts/truetype/freefont/FreeMono.ttf",16)) + printf("W: Font load failed.\n"); + pos[0]=-0;pos[1]=70;pos[2]=20; + rot[0]=0;rot[1]=90;rot[2]=90;ctk=0; + rendererTh=new std::thread(&SMELT::smMainLoop,sm); +} +void qmpVisualization::close() +{ + sm->smFinale(); + font.releaseTTF(); + sm->smTextureFree(chequer); + sm->smTargetFree(tdscn); + sm->smRelease(); +} +void qmpVisualization::reset() +{ + for(unsigned i=0;i<pool.size();++i)delete pool[i]; + pool.clear(); + for(int i=0;i<16;++i)for(int j=0;j<128;++j) + { + while(!pendingt[i][j].empty())pendingt[i][j].pop(); + while(!pendingv[i][j].empty())pendingv[i][j].pop(); + } +} +bool qmpVisualization::update() +{ + smQuad q; + for(int i=0;i<4;++i) + {q.v[i].col=0xFF999999;q.v[i].z=0;} + q.tex=chequer;q.blend=BLEND_ALPHABLEND; + q.v[0].x=q.v[3].x=-60;q.v[1].x=q.v[2].x=60; + q.v[0].y=q.v[1].y=-60;q.v[2].y=q.v[3].y=60; + q.v[0].tx=q.v[3].tx=0;q.v[1].tx=q.v[2].tx=15; + q.v[0].ty=q.v[1].ty=0;q.v[2].ty=q.v[3].ty=15; + sm->smRenderBegin3D(60,tdscn); + sm->sm3DCamera6f2v(pos,rot); + sm->smClrscr(0xFF666666); + sm->smRenderQuad(&q); + if(sm->smGetKeyState(SMK_D))pos[0]+=cos(smMath::deg2rad(rot[2]-90)),pos[1]+=sin(smMath::deg2rad(rot[2]-90)); + if(sm->smGetKeyState(SMK_A))pos[0]-=cos(smMath::deg2rad(rot[2]-90)),pos[1]-=sin(smMath::deg2rad(rot[2]-90)); + if(sm->smGetKeyState(SMK_S))pos[0]+=cos(smMath::deg2rad(rot[2])),pos[1]+=sin(smMath::deg2rad(rot[2])); + if(sm->smGetKeyState(SMK_W))pos[0]-=cos(smMath::deg2rad(rot[2])),pos[1]-=sin(smMath::deg2rad(rot[2])); + if(sm->smGetKeyState(SMK_Q))pos[2]+=1; + if(sm->smGetKeyState(SMK_E))pos[2]-=1; + if(sm->smGetKeyState(SMK_LBUTTON)==SMKST_HIT) + sm->smSetMouseGrab(true),sm->smGetMouse2f(&lastx,&lasty); + if(sm->smGetKeyState(SMK_LBUTTON)==SMKST_KEEP) + { + float x,y; + sm->smGetMouse2f(&x,&y); + rot[1]-=(y-lasty)*0.01; + rot[2]+=(x-lastx)*0.01; + while(rot[1]>360)rot[1]-=360; + while(rot[1]<0)rot[1]+=360; + while(rot[2]>360)rot[2]-=360; + while(rot[2]<0)rot[2]+=360; + } + if(sm->smGetKeyState(SMK_LBUTTON)==SMKST_RELEASE) + sm->smSetMouseGrab(false); + if(sm->smGetKeyState(SMK_I))rot[1]+=1; + if(sm->smGetKeyState(SMK_K))rot[1]-=1; + if(sm->smGetKeyState(SMK_L))rot[0]+=1; + if(sm->smGetKeyState(SMK_J))rot[0]-=1; + if(sm->smGetKeyState(SMK_U))rot[2]+=1; + if(sm->smGetKeyState(SMK_O))rot[2]-=1; + //printf("pos: %f %f %f\n",pos[0],pos[1],pos[2]); + //printf("rot: %f %f %f\n",rot[0],rot[1],rot[2]); + double lpt=(double)notestretch/dvs/10.; + for(uint32_t i=0;i<pool.size();++i)//need optimisation here + { + if(fabs((double)pool[i]->tcs-ctk)*lpt<viewdist*2||fabs((double)pool[i]->tce-ctk)*lpt<viewdist*2) + { + smvec3d a(((double)pool[i]->key-64),pool[i]->ch*-2.,((double)pool[i]->tce-ctk)*lpt); + smvec3d b(((double)pool[i]->key-64)+.9,pool[i]->ch*-2.+1.6,((double)pool[i]->tcs-ctk)*lpt); + if(((double)pool[i]->tce-pool[i]->tcs)*lpt<minnotelength/100.)a.z=((double)pool[i]->tcs-ctk)*lpt-minnotelength/100.; + drawCube(a,b,SETA(chcolors[pool[i]->ch],pool[i]->vel),0); + } + } + //ctk+=(int)(etps*sm->smGetDelta()); + ctk=api->getCurrentTimeStamp(); + if(ctk>fintk)return true; + sm->smRenderEnd(); + for(int i=0;i<4;++i){q.v[i].col=0xFFFFFFFF;q.v[i].z=0;} + q.tex=sm->smTargetTexture(tdscn); + sm->smRenderBegin2D(); + sm->smClrscr(0xFF000000); + q.v[0].tx=q.v[3].tx=0;q.v[1].tx=q.v[2].tx=1; + q.v[0].ty=q.v[1].ty=0;q.v[2].ty=q.v[3].ty=1; + q.v[0].x=q.v[1].x=0;q.v[2].x=q.v[3].x=800; + q.v[0].y=q.v[3].y=0;q.v[1].y=q.v[2].y=600; + sm->smRenderQuad(&q); + font.updateString(L"FPS: %.2f",sm->smGetFPS()); + font.render(1,586,0xFFFFFFFF,ALIGN_LEFT); + font.render(0,585,0xFF000000,ALIGN_LEFT); + sm->smRenderEnd(); + return false; +} + +void qmpVisualization::drawCube(smvec3d a,smvec3d b,DWORD col,SMTEX tex) +{ + smQuad q;q.blend=BLEND_ALPHABLEND; + q.tex=tex;for(int i=0;i<4;++i)q.v[i].col=col; + //top + q.v[0].x=a.x;q.v[0].y=a.y;q.v[0].z=a.z; + q.v[1].x=b.x;q.v[1].y=a.y;q.v[1].z=a.z; + q.v[2].x=b.x;q.v[2].y=b.y;q.v[2].z=a.z; + q.v[3].x=a.x;q.v[3].y=b.y;q.v[3].z=a.z; + sm->smRenderQuad(&q); + //bottom + q.v[0].x=a.x;q.v[0].y=a.y;q.v[0].z=b.z; + q.v[1].x=b.x;q.v[1].y=a.y;q.v[1].z=b.z; + q.v[2].x=b.x;q.v[2].y=b.y;q.v[2].z=b.z; + q.v[3].x=a.x;q.v[3].y=b.y;q.v[3].z=b.z; + sm->smRenderQuad(&q); + //left + q.v[0].x=a.x;q.v[0].y=b.y;q.v[0].z=a.z; + q.v[1].x=a.x;q.v[1].y=b.y;q.v[1].z=b.z; + q.v[2].x=a.x;q.v[2].y=a.y;q.v[2].z=b.z; + q.v[3].x=a.x;q.v[3].y=a.y;q.v[3].z=a.z; + sm->smRenderQuad(&q); + //right + q.v[0].x=b.x;q.v[0].y=b.y;q.v[0].z=a.z; + q.v[1].x=b.x;q.v[1].y=b.y;q.v[1].z=b.z; + q.v[2].x=b.x;q.v[2].y=a.y;q.v[2].z=b.z; + q.v[3].x=b.x;q.v[3].y=a.y;q.v[3].z=a.z; + sm->smRenderQuad(&q); + //front + q.v[0].x=a.x;q.v[0].y=b.y;q.v[0].z=a.z; + q.v[1].x=b.x;q.v[1].y=b.y;q.v[1].z=a.z; + q.v[2].x=b.x;q.v[2].y=b.y;q.v[2].z=b.z; + q.v[3].x=a.x;q.v[3].y=b.y;q.v[3].z=b.z; + sm->smRenderQuad(&q); + //back + q.v[0].x=a.x;q.v[0].y=a.y;q.v[0].z=a.z; + q.v[1].x=b.x;q.v[1].y=a.y;q.v[1].z=a.z; + q.v[2].x=b.x;q.v[2].y=a.y;q.v[2].z=b.z; + q.v[3].x=a.x;q.v[3].y=a.y;q.v[3].z=b.z; + sm->smRenderQuad(&q); +} -qmpVisualization::qmpVisualization(qmpPluginAPI* _api) -{api=_api;} -qmpVisualization::~qmpVisualization() -{api=NULL;} +qmpVisualization::qmpVisualization(qmpPluginAPI* _api){api=_api;} +qmpVisualization::~qmpVisualization(){api=NULL;} void qmpVisualization::init() { puts("hello world from test plugin!"); - puts("I'll try to print the first 3 events from the file!"); - cb=new CTestCallBack(this);c=0; - //!!FIXME: not working properly... + cb=new CTestCallBack(this); + vi=new CDemoVisualization(this); + h=new CMidiVisualHandler(this); + api->registerVisualizationIntf(vi); api->registerEventReaderIntf(cb,NULL); } void qmpVisualization::deinit() -{} +{ + delete cb;delete vi; + delete h; +} const char* qmpVisualization::pluginGetName() {return "QMidiPlayer Default Visualization Plugin";} const char* qmpVisualization::pluginGetVersion() {return "0.7.8";} +void qmpVisualization::pushNoteOn(uint32_t tc,uint32_t ch,uint32_t key,uint32_t vel) +{ + pendingt[ch][key].push(tc); + pendingv[ch][key].push(vel); +} +void qmpVisualization::pushNoteOff(uint32_t tc,uint32_t ch,uint32_t key) +{ + if(pendingt[ch][key].size()<1)return; + MidiVisualEvent *ne=new MidiVisualEvent(); + ne->tcs=pendingt[ch][key].top();pendingt[ch][key].pop(); + ne->tce=tc;ne->ch=ch;ne->key=key; + ne->vel=pendingv[ch][key].top();pendingv[ch][key].pop(); + if(tc>fintk)fintk=tc; +} + //dummy implementations of the api... uint32_t qmpPluginAPI::getDivision(){return 0;} uint32_t qmpPluginAPI::getRawTempo(){return 0;} @@ -43,3 +227,11 @@ int qmpPluginAPI::registerEventHandlerIntf(IMidiCallBack*,void*){return -1;} void qmpPluginAPI::unregisterEventHandlerIntf(int){} int qmpPluginAPI::registerEventReaderIntf(IMidiCallBack*,void*){return -1;} void qmpPluginAPI::unregisterEventReaderIntf(int){} +int qmpPluginAPI::registerVisualizationIntf(qmpVisualizationIntf*){return 0;} +void qmpPluginAPI::unregisterVisualizationIntf(int){} +void qmpPluginAPI::registerOptionInt(std::string,std::string,int){} +int qmpPluginAPI::getOptionInt(std::string){return 0;} +void qmpPluginAPI::registerOptionDouble(std::string,std::string,double){} +double qmpPluginAPI::getOptionDouble(std::string){return 0;} +void qmpPluginAPI::registerOptionString(std::string,std::string,std::string){} +std::string qmpPluginAPI::getOptionString(std::string){return "";} |