From 70fd2d85c1bd6fb8732e680e8fda9d36c317c732 Mon Sep 17 00:00:00 2001 From: Chris Xiong <chirs241097@gmail.com> Date: Wed, 6 Apr 2016 16:54:29 +0800 Subject: Too young too simple. --- README.md | 5 + common/qmpmidiplay.cpp | 404 --------------- common/qmpmidiplay.hpp | 137 ----- common/qmpmidiread.cpp | 239 --------- core/qmpmidiplay.cpp | 404 +++++++++++++++ core/qmpmidiplay.hpp | 137 +++++ core/qmpmidiread.cpp | 239 +++++++++ debian/changelog | 24 + debian/control | 13 +- debian/qmidiplayer-lite.install | 1 + debian/qmidiplayer.install | 1 + debian/rules | 2 +- qmidiplayer-desktop/main.cpp | 29 ++ qmidiplayer-desktop/qdialskulpturestyle.cpp | 437 ++++++++++++++++ qmidiplayer-desktop/qdialskulpturestyle.hpp | 39 ++ qmidiplayer-desktop/qmidiplayer-desktop.pro | 64 +++ qmidiplayer-desktop/qmpchanneleditor.cpp | 193 +++++++ qmidiplayer-desktop/qmpchanneleditor.hpp | 42 ++ qmidiplayer-desktop/qmpchanneleditor.ui | 602 ++++++++++++++++++++++ qmidiplayer-desktop/qmpchannelswindow.cpp | 132 +++++ qmidiplayer-desktop/qmpchannelswindow.hpp | 71 +++ qmidiplayer-desktop/qmpchannelswindow.ui | 146 ++++++ qmidiplayer-desktop/qmpefxwindow.cpp | 198 ++++++++ qmidiplayer-desktop/qmpefxwindow.hpp | 62 +++ qmidiplayer-desktop/qmpefxwindow.ui | 478 +++++++++++++++++ qmidiplayer-desktop/qmphelpwindow.cpp | 31 ++ qmidiplayer-desktop/qmphelpwindow.hpp | 26 + qmidiplayer-desktop/qmphelpwindow.ui | 34 ++ qmidiplayer-desktop/qmpimidimapper.hpp | 16 + qmidiplayer-desktop/qmpinfowindow.cpp | 57 +++ qmidiplayer-desktop/qmpinfowindow.hpp | 24 + qmidiplayer-desktop/qmpinfowindow.ui | 91 ++++ qmidiplayer-desktop/qmpmainwindow.cpp | 510 +++++++++++++++++++ qmidiplayer-desktop/qmpmainwindow.hpp | 90 ++++ qmidiplayer-desktop/qmpmainwindow.ui | 413 +++++++++++++++ qmidiplayer-desktop/qmpplistwindow.cpp | 308 +++++++++++ qmidiplayer-desktop/qmpplistwindow.hpp | 57 +++ qmidiplayer-desktop/qmpplistwindow.ui | 263 ++++++++++ qmidiplayer-desktop/qmppresetselect.cpp | 99 ++++ qmidiplayer-desktop/qmppresetselect.hpp | 36 ++ qmidiplayer-desktop/qmppresetselect.ui | 106 ++++ qmidiplayer-desktop/qmpsettingswindow.cpp | 289 +++++++++++ qmidiplayer-desktop/qmpsettingswindow.hpp | 47 ++ qmidiplayer-desktop/qmpsettingswindow.ui | 761 ++++++++++++++++++++++++++++ qmidiplayer-desktop/resources.qrc | 36 ++ qmidiplayer-lite/deployment.pri | 13 + qmidiplayer-lite/main.cpp | 15 + qmidiplayer-lite/main.qml | 144 ++++++ qmidiplayer-lite/qmidiplayer-lite.pro | 24 + qmidiplayer-lite/qml.qrc | 5 + qmidiplayer-lite/qmpcorewrapper.hpp | 58 +++ qmidiplayer-lite/qmpmidiplay.cpp | 406 +++++++++++++++ qmidiplayer-lite/qmpmidiplay.hpp | 137 +++++ qmidiplayer-lite/qmpmidiread.cpp | 240 +++++++++ qmidiplayer.pro | 67 +-- 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 --------- 96 files changed, 7656 insertions(+), 7611 deletions(-) delete mode 100644 common/qmpmidiplay.cpp delete mode 100644 common/qmpmidiplay.hpp delete mode 100644 common/qmpmidiread.cpp create mode 100644 core/qmpmidiplay.cpp create mode 100644 core/qmpmidiplay.hpp create mode 100644 core/qmpmidiread.cpp create mode 100644 debian/qmidiplayer-lite.install create mode 100644 debian/qmidiplayer.install create mode 100644 qmidiplayer-desktop/main.cpp create mode 100644 qmidiplayer-desktop/qdialskulpturestyle.cpp create mode 100644 qmidiplayer-desktop/qdialskulpturestyle.hpp create mode 100644 qmidiplayer-desktop/qmidiplayer-desktop.pro create mode 100644 qmidiplayer-desktop/qmpchanneleditor.cpp create mode 100644 qmidiplayer-desktop/qmpchanneleditor.hpp create mode 100644 qmidiplayer-desktop/qmpchanneleditor.ui create mode 100644 qmidiplayer-desktop/qmpchannelswindow.cpp create mode 100644 qmidiplayer-desktop/qmpchannelswindow.hpp create mode 100644 qmidiplayer-desktop/qmpchannelswindow.ui create mode 100644 qmidiplayer-desktop/qmpefxwindow.cpp create mode 100644 qmidiplayer-desktop/qmpefxwindow.hpp create mode 100644 qmidiplayer-desktop/qmpefxwindow.ui create mode 100644 qmidiplayer-desktop/qmphelpwindow.cpp create mode 100644 qmidiplayer-desktop/qmphelpwindow.hpp create mode 100644 qmidiplayer-desktop/qmphelpwindow.ui create mode 100644 qmidiplayer-desktop/qmpimidimapper.hpp create mode 100644 qmidiplayer-desktop/qmpinfowindow.cpp create mode 100644 qmidiplayer-desktop/qmpinfowindow.hpp create mode 100644 qmidiplayer-desktop/qmpinfowindow.ui create mode 100644 qmidiplayer-desktop/qmpmainwindow.cpp create mode 100644 qmidiplayer-desktop/qmpmainwindow.hpp create mode 100644 qmidiplayer-desktop/qmpmainwindow.ui create mode 100644 qmidiplayer-desktop/qmpplistwindow.cpp create mode 100644 qmidiplayer-desktop/qmpplistwindow.hpp create mode 100644 qmidiplayer-desktop/qmpplistwindow.ui create mode 100644 qmidiplayer-desktop/qmppresetselect.cpp create mode 100644 qmidiplayer-desktop/qmppresetselect.hpp create mode 100644 qmidiplayer-desktop/qmppresetselect.ui create mode 100644 qmidiplayer-desktop/qmpsettingswindow.cpp create mode 100644 qmidiplayer-desktop/qmpsettingswindow.hpp create mode 100644 qmidiplayer-desktop/qmpsettingswindow.ui create mode 100644 qmidiplayer-desktop/resources.qrc create mode 100644 qmidiplayer-lite/deployment.pri create mode 100644 qmidiplayer-lite/main.cpp create mode 100644 qmidiplayer-lite/main.qml create mode 100644 qmidiplayer-lite/qmidiplayer-lite.pro create mode 100644 qmidiplayer-lite/qml.qrc create mode 100644 qmidiplayer-lite/qmpcorewrapper.hpp create mode 100644 qmidiplayer-lite/qmpmidiplay.cpp create mode 100644 qmidiplayer-lite/qmpmidiplay.hpp create mode 100644 qmidiplayer-lite/qmpmidiread.cpp delete mode 100644 qmidiplayer.src.d/main.cpp delete mode 100644 qmidiplayer.src.d/qdialskulpturestyle.cpp delete mode 100644 qmidiplayer.src.d/qdialskulpturestyle.hpp delete mode 100644 qmidiplayer.src.d/qmpchanneleditor.cpp delete mode 100644 qmidiplayer.src.d/qmpchanneleditor.hpp delete mode 100644 qmidiplayer.src.d/qmpchanneleditor.ui delete mode 100644 qmidiplayer.src.d/qmpchannelswindow.cpp delete mode 100644 qmidiplayer.src.d/qmpchannelswindow.hpp delete mode 100644 qmidiplayer.src.d/qmpchannelswindow.ui delete mode 100644 qmidiplayer.src.d/qmpefxwindow.cpp delete mode 100644 qmidiplayer.src.d/qmpefxwindow.hpp delete mode 100644 qmidiplayer.src.d/qmpefxwindow.ui delete mode 100644 qmidiplayer.src.d/qmphelpwindow.cpp delete mode 100644 qmidiplayer.src.d/qmphelpwindow.hpp delete mode 100644 qmidiplayer.src.d/qmphelpwindow.ui delete mode 100644 qmidiplayer.src.d/qmpimidimapper.hpp delete mode 100644 qmidiplayer.src.d/qmpinfowindow.cpp delete mode 100644 qmidiplayer.src.d/qmpinfowindow.hpp delete mode 100644 qmidiplayer.src.d/qmpinfowindow.ui delete mode 100644 qmidiplayer.src.d/qmpmainwindow.cpp delete mode 100644 qmidiplayer.src.d/qmpmainwindow.hpp delete mode 100644 qmidiplayer.src.d/qmpmainwindow.ui delete mode 100644 qmidiplayer.src.d/qmpplistwindow.cpp delete mode 100644 qmidiplayer.src.d/qmpplistwindow.hpp delete mode 100644 qmidiplayer.src.d/qmpplistwindow.ui delete mode 100644 qmidiplayer.src.d/qmppresetselect.cpp delete mode 100644 qmidiplayer.src.d/qmppresetselect.hpp delete mode 100644 qmidiplayer.src.d/qmppresetselect.ui delete mode 100644 qmidiplayer.src.d/qmpsettingswindow.cpp delete mode 100644 qmidiplayer.src.d/qmpsettingswindow.hpp delete mode 100644 qmidiplayer.src.d/qmpsettingswindow.ui delete mode 100644 qmidiplayer.src.d/resources.qrc delete mode 100644 qmidiplayerlite.pro delete mode 100644 qmidiplayerlite.src.d/deployment.pri delete mode 100644 qmidiplayerlite.src.d/main.cpp delete mode 100644 qmidiplayerlite.src.d/main.qml delete mode 100644 qmidiplayerlite.src.d/qml.qrc delete mode 100644 qmidiplayerlite.src.d/qmpcorewrapper.hpp delete mode 100644 qmidiplayerlite.src.d/qmpmidiplay.cpp delete mode 100644 qmidiplayerlite.src.d/qmpmidiplay.hpp delete mode 100644 qmidiplayerlite.src.d/qmpmidiread.cpp diff --git a/README.md b/README.md index 758bb43..1d8319c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ # QMidiPlayer A cross-platform midi file player based on libfluidsynth and Qt. +[Project homepage](https://chrisoft.org/QMidiPlayer/) + Now it's in beta stage. Crashes and hangs may still occur, run with gdb attatched if you could. Features: @@ -10,5 +12,8 @@ Features: * Editing synthesizer effects * Rendering midi to wave file * Visualization using SMELT (not implemented) +* MIDI mapping (not implemented) Tested on Debian sid and Windows Vista~10. + +A QML version is now in construction. The whole project is now being overhauled... diff --git a/common/qmpmidiplay.cpp b/common/qmpmidiplay.cpp deleted file mode 100644 index 6f69e33..0000000 --- a/common/qmpmidiplay.cpp +++ /dev/null @@ -1,404 +0,0 @@ -#include <cstdio> -#include <chrono> -#include <thread> -#include <fluidsynth.h> -#include "qmpmidiplay.hpp" -#ifdef _WIN32 -#include <windows.h> -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)*1000000<t*pf); - timeEndPeriod(1); -} -#endif -void CMidiPlayer::playEvents() -{ - for(uint32_t ct=midiFile->getEvent(0)->time;tceptr<midiFile->getEventCount();) - { - while(tcpaused)std::this_thread::sleep_for(std::chrono::milliseconds(100)); - while(!tcstop&&midiFile&&tceptr<midiFile->getEventCount()&&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;eptr<midiFile->getEventCount();) - { - while(eptr<midiFile->getEventCount()&&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;eptr<midiFile->getEventCount();) - { - while(eptr<midiFile->getEventCount()&&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<<bn);} -void CMidiPlayer::setMute(int ch,bool m) -{setBit(mute,ch,m?1:0);} -void CMidiPlayer::setSolo(int ch,bool s) -{setBit(solo,ch,s?1:0);} -int CMidiPlayer::getCC(int ch, int id) -{int ret=0;synth?fluid_synth_get_cc(synth,ch,id,&ret):0;return ret;} -void CMidiPlayer::setCC(int ch, int id, int val) -{synth?fluid_synth_cc(synth,ch,id,val):0;} -void CMidiPlayer::getReverbPara(double *r,double *d,double *w,double *l) -{ - if(!synth)return; - *r=fluid_synth_get_reverb_roomsize(synth); - *d=fluid_synth_get_reverb_damp(synth); - *w=fluid_synth_get_reverb_width(synth); - *l=fluid_synth_get_reverb_level(synth); -} -void CMidiPlayer::setReverbPara(int e,double r,double d,double w,double l) -{ - if(!synth)return; - fluid_synth_set_reverb_on(synth,e); - fluid_synth_set_reverb(synth,r,d,w,l); -} -void CMidiPlayer::getChorusPara(int *fb,double *l,double *r,double *d,int *type) -{ - if(!synth)return; - *fb=fluid_synth_get_chorus_nr(synth); - *l=fluid_synth_get_chorus_level(synth); - *r=fluid_synth_get_chorus_speed_Hz(synth); - *d=fluid_synth_get_chorus_depth_ms(synth); - *type=fluid_synth_get_chorus_type(synth); -} -void CMidiPlayer::setChorusPara(int e,int fb,double l,double r,double d,int type) -{ - if(!synth)return; - fluid_synth_set_chorus_on(synth,e); - fluid_synth_set_chorus(synth,fb,l,r,d,type); -} -fluid_settings_t* CMidiPlayer::getFluidSettings(){return settings;} -void CMidiPlayer::pushSoundFont(const char *sf) -{fluid_synth_sfload(synth,sf,1);} -int CMidiPlayer::getSFCount() -{return synth?fluid_synth_sfcount(synth):0;} -fluid_sfont_t* CMidiPlayer::getSFPtr(int sfid) -{return synth&&sfid<getSFCount()?fluid_synth_get_sfont(synth,sfid):NULL;} diff --git a/common/qmpmidiplay.hpp b/common/qmpmidiplay.hpp deleted file mode 100644 index fafd677..0000000 --- a/common/qmpmidiplay.hpp +++ /dev/null @@ -1,137 +0,0 @@ -//sorry for the stupid C-like code... -#ifndef QMPMIDIPLAY_H -#define QMPMIDIPLAY_H -#include <cstring> -#include <cstdint> -#include <cstdlib> -#include <fluidsynth.h> -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 deleted file mode 100644 index fd2e0d9..0000000 --- a/common/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 <cstdio> -#include <cstring> -#include <cstdlib> -#include <cstdint> -#include <cstdarg> -#include <algorithm> -#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->time<b->time:a->iid<b->iid;} -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;c<len;++c) - { - ++byteread;if(str)str[c]=fgetc(f);else fgetc(f); - } - if(str)str[c]='\0';eventList[eventc++]=new SEvent(curid,curt,type,metatype,0,str); - if(str&&metatype==0x03&&!title) - { - title=new char[len+8]; - strcpy(title,str); - } - if(str&&metatype==0x02&&!copyright) - { - copyright=new char[len+8]; - strcpy(copyright,str); - } - if(len<=1024&&len>0)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;c<len;++c){++byteread;str[c]=fgetc(f);} - } - else for(c=0;c<len;++c){++byteread;str[c]=fgetc(f);} - eventList[eventc++]=new SEvent(curid,curt,type,len,0,str); - if(!strcmp(str,GM1SysX))std=1; - if(!strcmp(str,GM2SysX))std=2; - if(!strcmp(str,GSSysEx))std=3; - if(!strcmp(str,XGSysEx))std=4; - } - else error(0,"W: Unknown event type %#x",type); - break; - default: - fseek(f,-1,SEEK_CUR);--byteread;type=lasttype;goto retry; - } - lasttype=type;++curid; - return 1; -} -void CMidiFile::trackChunkReader() -{ - int chnklen=readDW();byteread=0;curt=0;curid=0; - while(/*byteread<chnklen&&*/eventReader()); - if(byteread<chnklen) - { - error(0,"W: Extra bytes after EOT event."); - while(byteread<chnklen){fgetc(f);++byteread;} - } - /*if(byteread>chnklen) - { - 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(;byteread<chnklen;++byteread){fgetc(f);} -} -int CMidiFile::chunkReader(int hdrXp) -{ - char hdr[6]; - if(!fgets(hdr,5,f))error(1,"E: Unexpected EOF."); - if(hdrXp) - if(strncmp(hdr,"MThd",4)){error(1,"E: Wrong MIDI header.");throw;} - else return headerChunkReader(),0; - else - if(strncmp(hdr,"MTrk",4)) - { - error(0,"W: Wrong track chunk header. Ignoring the whole chunk."); - for(int chnklen=readDW();chnklen>0;--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<trk;i+=chunkReader(0)); - fclose(f); - std::sort(eventList,eventList+eventc,cmp); - } - catch(int){fprintf(stderr,"E: %s is not a supported file.\n",fn);valid=0;} -} -CMidiFile::~CMidiFile() -{ - for(uint32_t i=0;i<eventc;++i)delete eventList[i]; - if(title)delete[] title;if(copyright)delete[] copyright; -} -const SEvent* CMidiFile::getEvent(uint32_t id){return id<eventc?eventList[id]:NULL;} -uint32_t CMidiFile::getEventCount(){return eventc;} -uint32_t CMidiFile::getDivision(){return divs;} -uint32_t CMidiFile::getNoteCount(){return notes;} -uint32_t CMidiFile::getStandard(){return std;} -bool CMidiFile::isValid(){return valid;} -const char* CMidiFile::getTitle(){return title;} -const char* CMidiFile::getCopyright(){return copyright;} diff --git a/core/qmpmidiplay.cpp b/core/qmpmidiplay.cpp new file mode 100644 index 0000000..6f69e33 --- /dev/null +++ b/core/qmpmidiplay.cpp @@ -0,0 +1,404 @@ +#include <cstdio> +#include <chrono> +#include <thread> +#include <fluidsynth.h> +#include "qmpmidiplay.hpp" +#ifdef _WIN32 +#include <windows.h> +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)*1000000<t*pf); + timeEndPeriod(1); +} +#endif +void CMidiPlayer::playEvents() +{ + for(uint32_t ct=midiFile->getEvent(0)->time;tceptr<midiFile->getEventCount();) + { + while(tcpaused)std::this_thread::sleep_for(std::chrono::milliseconds(100)); + while(!tcstop&&midiFile&&tceptr<midiFile->getEventCount()&&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;eptr<midiFile->getEventCount();) + { + while(eptr<midiFile->getEventCount()&&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;eptr<midiFile->getEventCount();) + { + while(eptr<midiFile->getEventCount()&&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<<bn);} +void CMidiPlayer::setMute(int ch,bool m) +{setBit(mute,ch,m?1:0);} +void CMidiPlayer::setSolo(int ch,bool s) +{setBit(solo,ch,s?1:0);} +int CMidiPlayer::getCC(int ch, int id) +{int ret=0;synth?fluid_synth_get_cc(synth,ch,id,&ret):0;return ret;} +void CMidiPlayer::setCC(int ch, int id, int val) +{synth?fluid_synth_cc(synth,ch,id,val):0;} +void CMidiPlayer::getReverbPara(double *r,double *d,double *w,double *l) +{ + if(!synth)return; + *r=fluid_synth_get_reverb_roomsize(synth); + *d=fluid_synth_get_reverb_damp(synth); + *w=fluid_synth_get_reverb_width(synth); + *l=fluid_synth_get_reverb_level(synth); +} +void CMidiPlayer::setReverbPara(int e,double r,double d,double w,double l) +{ + if(!synth)return; + fluid_synth_set_reverb_on(synth,e); + fluid_synth_set_reverb(synth,r,d,w,l); +} +void CMidiPlayer::getChorusPara(int *fb,double *l,double *r,double *d,int *type) +{ + if(!synth)return; + *fb=fluid_synth_get_chorus_nr(synth); + *l=fluid_synth_get_chorus_level(synth); + *r=fluid_synth_get_chorus_speed_Hz(synth); + *d=fluid_synth_get_chorus_depth_ms(synth); + *type=fluid_synth_get_chorus_type(synth); +} +void CMidiPlayer::setChorusPara(int e,int fb,double l,double r,double d,int type) +{ + if(!synth)return; + fluid_synth_set_chorus_on(synth,e); + fluid_synth_set_chorus(synth,fb,l,r,d,type); +} +fluid_settings_t* CMidiPlayer::getFluidSettings(){return settings;} +void CMidiPlayer::pushSoundFont(const char *sf) +{fluid_synth_sfload(synth,sf,1);} +int CMidiPlayer::getSFCount() +{return synth?fluid_synth_sfcount(synth):0;} +fluid_sfont_t* CMidiPlayer::getSFPtr(int sfid) +{return synth&&sfid<getSFCount()?fluid_synth_get_sfont(synth,sfid):NULL;} diff --git a/core/qmpmidiplay.hpp b/core/qmpmidiplay.hpp new file mode 100644 index 0000000..fafd677 --- /dev/null +++ b/core/qmpmidiplay.hpp @@ -0,0 +1,137 @@ +//sorry for the stupid C-like code... +#ifndef QMPMIDIPLAY_H +#define QMPMIDIPLAY_H +#include <cstring> +#include <cstdint> +#include <cstdlib> +#include <fluidsynth.h> +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/core/qmpmidiread.cpp b/core/qmpmidiread.cpp new file mode 100644 index 0000000..fd2e0d9 --- /dev/null +++ b/core/qmpmidiread.cpp @@ -0,0 +1,239 @@ +//CLI Midi file player based on libfluidsynth +//Midi file reading module +//Written by Chris Xiong, 2015 +#include <cstdio> +#include <cstring> +#include <cstdlib> +#include <cstdint> +#include <cstdarg> +#include <algorithm> +#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->time<b->time:a->iid<b->iid;} +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;c<len;++c) + { + ++byteread;if(str)str[c]=fgetc(f);else fgetc(f); + } + if(str)str[c]='\0';eventList[eventc++]=new SEvent(curid,curt,type,metatype,0,str); + if(str&&metatype==0x03&&!title) + { + title=new char[len+8]; + strcpy(title,str); + } + if(str&&metatype==0x02&&!copyright) + { + copyright=new char[len+8]; + strcpy(copyright,str); + } + if(len<=1024&&len>0)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;c<len;++c){++byteread;str[c]=fgetc(f);} + } + else for(c=0;c<len;++c){++byteread;str[c]=fgetc(f);} + eventList[eventc++]=new SEvent(curid,curt,type,len,0,str); + if(!strcmp(str,GM1SysX))std=1; + if(!strcmp(str,GM2SysX))std=2; + if(!strcmp(str,GSSysEx))std=3; + if(!strcmp(str,XGSysEx))std=4; + } + else error(0,"W: Unknown event type %#x",type); + break; + default: + fseek(f,-1,SEEK_CUR);--byteread;type=lasttype;goto retry; + } + lasttype=type;++curid; + return 1; +} +void CMidiFile::trackChunkReader() +{ + int chnklen=readDW();byteread=0;curt=0;curid=0; + while(/*byteread<chnklen&&*/eventReader()); + if(byteread<chnklen) + { + error(0,"W: Extra bytes after EOT event."); + while(byteread<chnklen){fgetc(f);++byteread;} + } + /*if(byteread>chnklen) + { + 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(;byteread<chnklen;++byteread){fgetc(f);} +} +int CMidiFile::chunkReader(int hdrXp) +{ + char hdr[6]; + if(!fgets(hdr,5,f))error(1,"E: Unexpected EOF."); + if(hdrXp) + if(strncmp(hdr,"MThd",4)){error(1,"E: Wrong MIDI header.");throw;} + else return headerChunkReader(),0; + else + if(strncmp(hdr,"MTrk",4)) + { + error(0,"W: Wrong track chunk header. Ignoring the whole chunk."); + for(int chnklen=readDW();chnklen>0;--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<trk;i+=chunkReader(0)); + fclose(f); + std::sort(eventList,eventList+eventc,cmp); + } + catch(int){fprintf(stderr,"E: %s is not a supported file.\n",fn);valid=0;} +} +CMidiFile::~CMidiFile() +{ + for(uint32_t i=0;i<eventc;++i)delete eventList[i]; + if(title)delete[] title;if(copyright)delete[] copyright; +} +const SEvent* CMidiFile::getEvent(uint32_t id){return id<eventc?eventList[id]:NULL;} +uint32_t CMidiFile::getEventCount(){return eventc;} +uint32_t CMidiFile::getDivision(){return divs;} +uint32_t CMidiFile::getNoteCount(){return notes;} +uint32_t CMidiFile::getStandard(){return std;} +bool CMidiFile::isValid(){return valid;} +const char* CMidiFile::getTitle(){return title;} +const char* CMidiFile::getCopyright(){return copyright;} diff --git a/debian/changelog b/debian/changelog index 6437ab1..a57c578 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,27 @@ +qmidiplayer (0.7.0-6) UNRELEASED; urgency=low + + * Package qmidiplayer-lite. + + -- chrisoft <chirs241097@gmail.com> Wed, 06 Apr 2016 16:45:02 +0800 + +qmidiplayer (0.7.0-5) UNRELEASED; urgency=low + + * New upstream release. + + -- chrisoft <chirs241097@gmail.com> Wed, 06 Apr 2016 09:43:57 +0800 + +qmidiplayer (0.7.0-4) UNRELEASED; urgency=low + + * New upstream release. + + -- chrisoft <chirs241097@gmail.com> Tue, 05 Apr 2016 22:17:31 +0800 + +qmidiplayer (0.7.0-3) UNRELEASED; urgency=low + + * New upstream release. + + -- chrisoft <chirs241097@gmail.com> Wed, 23 Mar 2016 15:41:15 +0800 + qmidiplayer (0.7.0-2) UNRELEASED; urgency=low * New upstream release. diff --git a/debian/control b/debian/control index c686b55..44eeaae 100644 --- a/debian/control +++ b/debian/control @@ -3,9 +3,18 @@ Maintainer: Chris Xiong <chirs241097@gmail.com> Section: sound Priority: optional Standards-Version: 3.9.2 -Build-Depends: debhelper (>= 9), qtbase5-dev, qt5-qmake, libfluidsynth-dev +Build-Depends: debhelper (>= 9), qtbase5-dev, qt5-qmake, libfluidsynth-dev, + qml-module-qtquick-controls, + qml-module-qtquick-window2, + qml-module-qtquick2, + libqt5qml5 Package: qmidiplayer Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends} -Description: Midi player based on Qt and fluidsynth. \ No newline at end of file +Description: Midi player based on Qt and fluidsynth. + +Package: qmidiplayer-lite +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends} +Description: Midi player based on Qt and fluidsynth (Lite version). diff --git a/debian/qmidiplayer-lite.install b/debian/qmidiplayer-lite.install new file mode 100644 index 0000000..ece593e --- /dev/null +++ b/debian/qmidiplayer-lite.install @@ -0,0 +1 @@ +usr/bin/qmidiplayer-lite diff --git a/debian/qmidiplayer.install b/debian/qmidiplayer.install new file mode 100644 index 0000000..ed86d84 --- /dev/null +++ b/debian/qmidiplayer.install @@ -0,0 +1 @@ +usr/bin/qmidiplayer diff --git a/debian/rules b/debian/rules index 589a09a..f88b391 100755 --- a/debian/rules +++ b/debian/rules @@ -2,4 +2,4 @@ %: dh $@ --parallel override_dh_auto_install: - $(MAKE) INSTALL_ROOT=$$(pwd)/debian/qmidiplayer prefix=/usr install \ No newline at end of file + $(MAKE) INSTALL_ROOT=$$(pwd)/debian/tmp prefix=/usr install \ No newline at end of file diff --git a/qmidiplayer-desktop/main.cpp b/qmidiplayer-desktop/main.cpp new file mode 100644 index 0000000..c9f3b42 --- /dev/null +++ b/qmidiplayer-desktop/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 <http://www.gnu.org/licenses/>. + */ +#include "qmpmainwindow.hpp" +#include <QApplication> +#include <QStyle> + +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-desktop/qdialskulpturestyle.cpp b/qmidiplayer-desktop/qdialskulpturestyle.cpp new file mode 100644 index 0000000..7c181a0 --- /dev/null +++ b/qmidiplayer-desktop/qdialskulpturestyle.cpp @@ -0,0 +1,437 @@ +/****************************************************************************** + + Skulpture - Classical Three-Dimensional Artwork for Qt 4 + + Copyright (c) 2007-2009 Christoph Feck <christoph@maxiom.de> + + 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 <cmath> +#include <QStyleOptionSlider> +#include <QPixmapCache> +#include <QPainter> + +#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<const QStyleOptionSlider *>(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<const QAbstractSlider *>(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-desktop/qdialskulpturestyle.hpp b/qmidiplayer-desktop/qdialskulpturestyle.hpp new file mode 100644 index 0000000..2f3ba04 --- /dev/null +++ b/qmidiplayer-desktop/qdialskulpturestyle.hpp @@ -0,0 +1,39 @@ +/****************************************************************************** + + Skulpture - Classical Three-Dimensional Artwork for Qt 4 + + Copyright (c) 2007-2009 Christoph Feck <christoph@maxiom.de> + + 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 <QCommonStyle> + +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-desktop/qmidiplayer-desktop.pro b/qmidiplayer-desktop/qmidiplayer-desktop.pro new file mode 100644 index 0000000..328af5d --- /dev/null +++ b/qmidiplayer-desktop/qmidiplayer-desktop.pro @@ -0,0 +1,64 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2015-12-25T20:24:49 +# +#------------------------------------------------- + +QT += core gui + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +TARGET = qmidiplayer +TEMPLATE = app + + +SOURCES += main.cpp\ + qmpmainwindow.cpp \ + ../core/qmpmidiplay.cpp \ + ../core/qmpmidiread.cpp \ + qmpplistwindow.cpp \ + qmpchannelswindow.cpp \ + qmppresetselect.cpp \ + qmpchanneleditor.cpp \ + qmpefxwindow.cpp \ + qmpinfowindow.cpp \ + qmpsettingswindow.cpp \ + qmphelpwindow.cpp \ + qdialskulpturestyle.cpp + +HEADERS += qmpmainwindow.hpp \ + ../core/qmpmidiplay.hpp \ + qmpplistwindow.hpp \ + qmpchannelswindow.hpp \ + qmppresetselect.hpp \ + qmpchanneleditor.hpp \ + qmpefxwindow.hpp \ + qmpinfowindow.hpp \ + qmpsettingswindow.hpp \ + qmphelpwindow.hpp \ + qdialskulpturestyle.hpp \ + qmpimidimapper.hpp + +FORMS += qmpmainwindow.ui \ + qmpplistwindow.ui \ + qmpchannelswindow.ui \ + qmppresetselect.ui \ + qmpchanneleditor.ui \ + qmpefxwindow.ui \ + qmpinfowindow.ui \ + qmpsettingswindow.ui \ + qmphelpwindow.ui + +unix{ + isEmpty(PREFIX) { + PREFIX = /usr/local + } + BINDIR = $$PREFIX/bin + target.path = $$BINDIR + INSTALLS += target + QMAKE_CXXFLAGS += -std=c++11 -Wall + LIBS += -lfluidsynth +} +win32:LIBS += e:/libs/fluidsynth/fluidsynth.lib winmm.lib #You have to change these +win32:INCLUDEPATH += e:/libs/fluidsynth/include #before building... +RESOURCES = resources.qrc diff --git a/qmidiplayer-desktop/qmpchanneleditor.cpp b/qmidiplayer-desktop/qmpchanneleditor.cpp new file mode 100644 index 0000000..f1d4e5e --- /dev/null +++ b/qmidiplayer-desktop/qmpchanneleditor.cpp @@ -0,0 +1,193 @@ +#include <cstdio> +#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<QDial*> dials=findChildren<QDial*>(); + for(int i=0;i<dials.count();++i) + dials.at(i)->setStyle(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-desktop/qmpchanneleditor.hpp b/qmidiplayer-desktop/qmpchanneleditor.hpp new file mode 100644 index 0000000..0653af5 --- /dev/null +++ b/qmidiplayer-desktop/qmpchanneleditor.hpp @@ -0,0 +1,42 @@ +#ifndef QMPCHANNELEDITOR_H +#define QMPCHANNELEDITOR_H + +#include <QDialog> +#include <QShowEvent> +#include <QCloseEvent> +#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-desktop/qmpchanneleditor.ui b/qmidiplayer-desktop/qmpchanneleditor.ui new file mode 100644 index 0000000..49e8c8e --- /dev/null +++ b/qmidiplayer-desktop/qmpchanneleditor.ui @@ -0,0 +1,602 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>qmpChannelEditor</class> + <widget class="QDialog" name="qmpChannelEditor"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>422</width> + <height>300</height> + </rect> + </property> + <property name="minimumSize"> + <size> + <width>422</width> + <height>300</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>422</width> + <height>300</height> + </size> + </property> + <property name="windowTitle"> + <string>Dialog</string> + </property> + <widget class="QPushButton" name="pbChLeft"> + <property name="geometry"> + <rect> + <x>10</x> + <y>10</y> + <width>21</width> + <height>21</height> + </rect> + </property> + <property name="text"> + <string><</string> + </property> + </widget> + <widget class="QLabel" name="lbChannelNumber"> + <property name="geometry"> + <rect> + <x>30</x> + <y>10</y> + <width>21</width> + <height>20</height> + </rect> + </property> + <property name="text"> + <string>1</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + <widget class="QPushButton" name="pbChRight"> + <property name="geometry"> + <rect> + <x>50</x> + <y>10</y> + <width>21</width> + <height>21</height> + </rect> + </property> + <property name="text"> + <string>></string> + </property> + </widget> + <widget class="QLabel" name="lbPresetName"> + <property name="geometry"> + <rect> + <x>90</x> + <y>10</y> + <width>261</width> + <height>51</height> + </rect> + </property> + <property name="font"> + <font> + <pointsize>16</pointsize> + </font> + </property> + <property name="text"> + <string>Yamaha Grand Piano</string> + </property> + </widget> + <widget class="QLabel" name="lbBank"> + <property name="geometry"> + <rect> + <x>10</x> + <y>30</y> + <width>81</width> + <height>20</height> + </rect> + </property> + <property name="text"> + <string>BK: 0</string> + </property> + </widget> + <widget class="QLabel" name="lbPreset"> + <property name="geometry"> + <rect> + <x>10</x> + <y>50</y> + <width>81</width> + <height>20</height> + </rect> + </property> + <property name="text"> + <string>PC: 0</string> + </property> + </widget> + <widget class="QGroupBox" name="gFilters"> + <property name="geometry"> + <rect> + <x>0</x> + <y>70</y> + <width>141</width> + <height>101</height> + </rect> + </property> + <property name="title"> + <string>Filters</string> + </property> + <widget class="QLabel" name="lbReso"> + <property name="geometry"> + <rect> + <x>70</x> + <y>80</y> + <width>66</width> + <height>20</height> + </rect> + </property> + <property name="text"> + <string>Res. 64</string> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + <widget class="QDial" name="dReso"> + <property name="geometry"> + <rect> + <x>80</x> + <y>30</y> + <width>50</width> + <height>51</height> + </rect> + </property> + <property name="maximum"> + <number>127</number> + </property> + <property name="value"> + <number>64</number> + </property> + <property name="notchesVisible"> + <bool>true</bool> + </property> + </widget> + <widget class="QDial" name="dCut"> + <property name="geometry"> + <rect> + <x>10</x> + <y>30</y> + <width>50</width> + <height>51</height> + </rect> + </property> + <property name="maximum"> + <number>127</number> + </property> + <property name="value"> + <number>64</number> + </property> + <property name="notchesVisible"> + <bool>true</bool> + </property> + </widget> + <widget class="QLabel" name="lbCut"> + <property name="geometry"> + <rect> + <x>0</x> + <y>80</y> + <width>71</width> + <height>20</height> + </rect> + </property> + <property name="text"> + <string>Cut. 64</string> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + </widget> + <widget class="QGroupBox" name="gEffects"> + <property name="geometry"> + <rect> + <x>140</x> + <y>70</y> + <width>141</width> + <height>101</height> + </rect> + </property> + <property name="title"> + <string>Effects</string> + </property> + <widget class="QLabel" name="lbChorus"> + <property name="geometry"> + <rect> + <x>70</x> + <y>80</y> + <width>66</width> + <height>20</height> + </rect> + </property> + <property name="text"> + <string>Chr. 64</string> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + <widget class="QDial" name="dChorus"> + <property name="geometry"> + <rect> + <x>80</x> + <y>30</y> + <width>50</width> + <height>51</height> + </rect> + </property> + <property name="maximum"> + <number>127</number> + </property> + <property name="value"> + <number>64</number> + </property> + <property name="notchesVisible"> + <bool>true</bool> + </property> + </widget> + <widget class="QDial" name="dReverb"> + <property name="geometry"> + <rect> + <x>10</x> + <y>30</y> + <width>50</width> + <height>51</height> + </rect> + </property> + <property name="maximum"> + <number>127</number> + </property> + <property name="value"> + <number>64</number> + </property> + <property name="notchesVisible"> + <bool>true</bool> + </property> + </widget> + <widget class="QLabel" name="lbReverb"> + <property name="geometry"> + <rect> + <x>0</x> + <y>80</y> + <width>71</width> + <height>20</height> + </rect> + </property> + <property name="text"> + <string>Rev. 64</string> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + </widget> + <widget class="QGroupBox" name="gEnvelope"> + <property name="geometry"> + <rect> + <x>0</x> + <y>170</y> + <width>211</width> + <height>101</height> + </rect> + </property> + <property name="title"> + <string>Envelope</string> + </property> + <widget class="QLabel" name="lbDecay"> + <property name="geometry"> + <rect> + <x>70</x> + <y>80</y> + <width>66</width> + <height>20</height> + </rect> + </property> + <property name="text"> + <string>Dec. 64</string> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + <widget class="QDial" name="dDecay"> + <property name="geometry"> + <rect> + <x>80</x> + <y>30</y> + <width>50</width> + <height>51</height> + </rect> + </property> + <property name="maximum"> + <number>127</number> + </property> + <property name="value"> + <number>64</number> + </property> + <property name="notchesVisible"> + <bool>true</bool> + </property> + </widget> + <widget class="QDial" name="dAttack"> + <property name="geometry"> + <rect> + <x>10</x> + <y>30</y> + <width>50</width> + <height>51</height> + </rect> + </property> + <property name="maximum"> + <number>127</number> + </property> + <property name="value"> + <number>64</number> + </property> + <property name="notchesVisible"> + <bool>true</bool> + </property> + </widget> + <widget class="QLabel" name="lbAttack"> + <property name="geometry"> + <rect> + <x>0</x> + <y>80</y> + <width>71</width> + <height>20</height> + </rect> + </property> + <property name="text"> + <string>Atk. 64</string> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + <widget class="QDial" name="dRelease"> + <property name="geometry"> + <rect> + <x>150</x> + <y>30</y> + <width>50</width> + <height>51</height> + </rect> + </property> + <property name="maximum"> + <number>127</number> + </property> + <property name="value"> + <number>64</number> + </property> + <property name="notchesVisible"> + <bool>true</bool> + </property> + </widget> + <widget class="QLabel" name="lbRelease"> + <property name="geometry"> + <rect> + <x>140</x> + <y>80</y> + <width>66</width> + <height>20</height> + </rect> + </property> + <property name="text"> + <string>Rel. 64</string> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + </widget> + <widget class="QGroupBox" name="gVibrato"> + <property name="geometry"> + <rect> + <x>210</x> + <y>170</y> + <width>211</width> + <height>101</height> + </rect> + </property> + <property name="title"> + <string>Vibrato</string> + </property> + <widget class="QLabel" name="lbDepth"> + <property name="geometry"> + <rect> + <x>70</x> + <y>80</y> + <width>66</width> + <height>20</height> + </rect> + </property> + <property name="text"> + <string>Dep. 64</string> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + <widget class="QDial" name="dDepth"> + <property name="geometry"> + <rect> + <x>80</x> + <y>30</y> + <width>50</width> + <height>51</height> + </rect> + </property> + <property name="maximum"> + <number>127</number> + </property> + <property name="value"> + <number>64</number> + </property> + <property name="notchesVisible"> + <bool>true</bool> + </property> + </widget> + <widget class="QDial" name="dRate"> + <property name="geometry"> + <rect> + <x>10</x> + <y>30</y> + <width>50</width> + <height>51</height> + </rect> + </property> + <property name="maximum"> + <number>127</number> + </property> + <property name="value"> + <number>64</number> + </property> + <property name="notchesVisible"> + <bool>true</bool> + </property> + </widget> + <widget class="QLabel" name="lbRate"> + <property name="geometry"> + <rect> + <x>0</x> + <y>80</y> + <width>71</width> + <height>20</height> + </rect> + </property> + <property name="text"> + <string>Rate 64</string> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + <widget class="QDial" name="dDelay"> + <property name="geometry"> + <rect> + <x>150</x> + <y>30</y> + <width>50</width> + <height>51</height> + </rect> + </property> + <property name="maximum"> + <number>127</number> + </property> + <property name="value"> + <number>64</number> + </property> + <property name="notchesVisible"> + <bool>true</bool> + </property> + </widget> + <widget class="QLabel" name="lbDelay"> + <property name="geometry"> + <rect> + <x>140</x> + <y>80</y> + <width>66</width> + <height>20</height> + </rect> + </property> + <property name="text"> + <string>Del. 64</string> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + </widget> + <widget class="QGroupBox" name="gMixer"> + <property name="geometry"> + <rect> + <x>280</x> + <y>70</y> + <width>141</width> + <height>101</height> + </rect> + </property> + <property name="title"> + <string>Mixer</string> + </property> + <widget class="QLabel" name="lbPan"> + <property name="geometry"> + <rect> + <x>70</x> + <y>80</y> + <width>66</width> + <height>20</height> + </rect> + </property> + <property name="text"> + <string>Pan. C</string> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + <widget class="QDial" name="dPan"> + <property name="geometry"> + <rect> + <x>80</x> + <y>30</y> + <width>50</width> + <height>51</height> + </rect> + </property> + <property name="maximum"> + <number>127</number> + </property> + <property name="value"> + <number>64</number> + </property> + <property name="notchesVisible"> + <bool>true</bool> + </property> + </widget> + <widget class="QLabel" name="lbVol"> + <property name="geometry"> + <rect> + <x>0</x> + <y>80</y> + <width>66</width> + <height>20</height> + </rect> + </property> + <property name="text"> + <string>Vol. 127</string> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + <widget class="QDial" name="dVol"> + <property name="geometry"> + <rect> + <x>10</x> + <y>30</y> + <width>50</width> + <height>51</height> + </rect> + </property> + <property name="maximum"> + <number>127</number> + </property> + <property name="value"> + <number>127</number> + </property> + <property name="notchesVisible"> + <bool>true</bool> + </property> + </widget> + </widget> + </widget> + <resources/> + <connections/> +</ui> diff --git a/qmidiplayer-desktop/qmpchannelswindow.cpp b/qmidiplayer-desktop/qmpchannelswindow.cpp new file mode 100644 index 0000000..a9cf60e --- /dev/null +++ b/qmidiplayer-desktop/qmpchannelswindow.cpp @@ -0,0 +1,132 @@ +#include <QCheckBox> +#include <QPushButton> +#include <QComboBox> +#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-desktop/qmpchannelswindow.hpp b/qmidiplayer-desktop/qmpchannelswindow.hpp new file mode 100644 index 0000000..f0591b6 --- /dev/null +++ b/qmidiplayer-desktop/qmpchannelswindow.hpp @@ -0,0 +1,71 @@ +#ifndef QMPCHANNELSWINDOW_H +#define QMPCHANNELSWINDOW_H + +#include <QLabel> +#include <QPushButton> +#include <QDialog> +#include <QShowEvent> +#include <QCloseEvent> +#include <QMoveEvent> +#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-desktop/qmpchannelswindow.ui b/qmidiplayer-desktop/qmpchannelswindow.ui new file mode 100644 index 0000000..a8b43cb --- /dev/null +++ b/qmidiplayer-desktop/qmpchannelswindow.ui @@ -0,0 +1,146 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>qmpChannelsWindow</class> + <widget class="QDialog" name="qmpChannelsWindow"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>580</width> + <height>410</height> + </rect> + </property> + <property name="minimumSize"> + <size> + <width>580</width> + <height>410</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>580</width> + <height>16777215</height> + </size> + </property> + <property name="windowTitle"> + <string>Channels</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_4"> + <item> + <layout class="QVBoxLayout" name="verticalLayout_1"> + <item> + <widget class="QTableWidget" name="twChannels"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="alternatingRowColors"> + <bool>true</bool> + </property> + <property name="selectionMode"> + <enum>QAbstractItemView::NoSelection</enum> + </property> + <property name="cornerButtonEnabled"> + <bool>false</bool> + </property> + <property name="rowCount"> + <number>16</number> + </property> + <property name="columnCount"> + <number>5</number> + </property> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <column> + <property name="text"> + <string>M</string> + </property> + </column> + <column> + <property name="text"> + <string>S</string> + </property> + </column> + <column> + <property name="text"> + <string>Device</string> + </property> + </column> + <column> + <property name="text"> + <string>Preset</string> + </property> + </column> + <column> + <property name="text"> + <string>...</string> + </property> + </column> + <item row="0" column="0"> + <property name="text"> + <string/> + </property> + </item> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QPushButton" name="pbSave"> + <property name="text"> + <string>Save</string> + </property> + <property name="iconSize"> + <size> + <width>16</width> + <height>16</height> + </size> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="pbLoad"> + <property name="text"> + <string>Load</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="pbUnmute"> + <property name="text"> + <string>Unmute All</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="pbUnsolo"> + <property name="text"> + <string>Unsolo All</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/qmidiplayer-desktop/qmpefxwindow.cpp b/qmidiplayer-desktop/qmpefxwindow.cpp new file mode 100644 index 0000000..7d9c08e --- /dev/null +++ b/qmidiplayer-desktop/qmpefxwindow.cpp @@ -0,0 +1,198 @@ +#include <cmath> +#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<QDial*> dials=findChildren<QDial*>(); + for(int i=0;i<dials.count();++i) + dials.at(i)->setStyle(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-desktop/qmpefxwindow.hpp b/qmidiplayer-desktop/qmpefxwindow.hpp new file mode 100644 index 0000000..2a080f0 --- /dev/null +++ b/qmidiplayer-desktop/qmpefxwindow.hpp @@ -0,0 +1,62 @@ +#ifndef QMPEFXWINDOW_HPP +#define QMPEFXWINDOW_HPP + +#include <QDialog> +#include <QCloseEvent> +#include <QShowEvent> +#include <QMoveEvent> + +#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-desktop/qmpefxwindow.ui b/qmidiplayer-desktop/qmpefxwindow.ui new file mode 100644 index 0000000..4a1e0c6 --- /dev/null +++ b/qmidiplayer-desktop/qmpefxwindow.ui @@ -0,0 +1,478 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>qmpEfxWindow</class> + <widget class="QDialog" name="qmpEfxWindow"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>546</width> + <height>177</height> + </rect> + </property> + <property name="minimumSize"> + <size> + <width>546</width> + <height>177</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>546</width> + <height>177</height> + </size> + </property> + <property name="windowTitle"> + <string>Effects</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QGroupBox" name="gReverb"> + <property name="title"> + <string>Reverb</string> + </property> + <widget class="QCheckBox" name="cbEnabledR"> + <property name="geometry"> + <rect> + <x>80</x> + <y>4</y> + <width>21</width> + <height>24</height> + </rect> + </property> + <property name="text"> + <string/> + </property> + </widget> + <widget class="QDial" name="dRoom"> + <property name="geometry"> + <rect> + <x>10</x> + <y>30</y> + <width>50</width> + <height>51</height> + </rect> + </property> + <property name="maximum"> + <number>120</number> + </property> + <property name="notchesVisible"> + <bool>true</bool> + </property> + </widget> + <widget class="QDial" name="dDamp"> + <property name="geometry"> + <rect> + <x>200</x> + <y>30</y> + <width>50</width> + <height>51</height> + </rect> + </property> + <property name="maximum"> + <number>100</number> + </property> + <property name="notchesVisible"> + <bool>true</bool> + </property> + </widget> + <widget class="QDial" name="dWidth"> + <property name="geometry"> + <rect> + <x>10</x> + <y>103</y> + <width>50</width> + <height>51</height> + </rect> + </property> + <property name="maximum"> + <number>100</number> + </property> + <property name="notchesVisible"> + <bool>true</bool> + </property> + </widget> + <widget class="QDial" name="dLevelR"> + <property name="geometry"> + <rect> + <x>200</x> + <y>103</y> + <width>50</width> + <height>51</height> + </rect> + </property> + <property name="maximum"> + <number>100</number> + </property> + <property name="notchesVisible"> + <bool>true</bool> + </property> + </widget> + <widget class="QLabel" name="lbRoom"> + <property name="geometry"> + <rect> + <x>60</x> + <y>30</y> + <width>41</width> + <height>20</height> + </rect> + </property> + <property name="text"> + <string>Room</string> + </property> + </widget> + <widget class="QSpinBox" name="sbRoom"> + <property name="geometry"> + <rect> + <x>60</x> + <y>50</y> + <width>51</width> + <height>21</height> + </rect> + </property> + <property name="maximum"> + <number>120</number> + </property> + </widget> + <widget class="QLabel" name="lbDamp"> + <property name="geometry"> + <rect> + <x>140</x> + <y>30</y> + <width>51</width> + <height>20</height> + </rect> + </property> + <property name="text"> + <string>Damp</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + <widget class="QSpinBox" name="sbDamp"> + <property name="geometry"> + <rect> + <x>140</x> + <y>50</y> + <width>56</width> + <height>21</height> + </rect> + </property> + <property name="maximum"> + <number>100</number> + </property> + </widget> + <widget class="QLabel" name="lbWidth"> + <property name="geometry"> + <rect> + <x>60</x> + <y>100</y> + <width>51</width> + <height>20</height> + </rect> + </property> + <property name="text"> + <string>Width</string> + </property> + </widget> + <widget class="QSpinBox" name="sbWidth"> + <property name="geometry"> + <rect> + <x>60</x> + <y>120</y> + <width>56</width> + <height>21</height> + </rect> + </property> + <property name="maximum"> + <number>100</number> + </property> + </widget> + <widget class="QLabel" name="lbLevelR"> + <property name="geometry"> + <rect> + <x>145</x> + <y>100</y> + <width>51</width> + <height>20</height> + </rect> + </property> + <property name="text"> + <string>Level</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + <widget class="QSpinBox" name="sbLevelR"> + <property name="geometry"> + <rect> + <x>140</x> + <y>120</y> + <width>56</width> + <height>21</height> + </rect> + </property> + <property name="maximum"> + <number>100</number> + </property> + </widget> + </widget> + </item> + <item> + <widget class="QGroupBox" name="gChorus"> + <property name="title"> + <string>Chorus</string> + </property> + <widget class="QCheckBox" name="cbEnabledC"> + <property name="geometry"> + <rect> + <x>80</x> + <y>4</y> + <width>21</width> + <height>24</height> + </rect> + </property> + <property name="text"> + <string/> + </property> + </widget> + <widget class="QDial" name="dFeedBack"> + <property name="geometry"> + <rect> + <x>10</x> + <y>30</y> + <width>50</width> + <height>51</height> + </rect> + </property> + <property name="maximum"> + <number>99</number> + </property> + <property name="notchesVisible"> + <bool>true</bool> + </property> + </widget> + <widget class="QDial" name="dRate"> + <property name="geometry"> + <rect> + <x>200</x> + <y>30</y> + <width>50</width> + <height>51</height> + </rect> + </property> + <property name="minimum"> + <number>29</number> + </property> + <property name="maximum"> + <number>500</number> + </property> + <property name="value"> + <number>29</number> + </property> + <property name="notchesVisible"> + <bool>true</bool> + </property> + </widget> + <widget class="QDial" name="dDepth"> + <property name="geometry"> + <rect> + <x>10</x> + <y>103</y> + <width>50</width> + <height>51</height> + </rect> + </property> + <property name="maximum"> + <number>210</number> + </property> + <property name="notchesVisible"> + <bool>true</bool> + </property> + </widget> + <widget class="QDial" name="dLevelC"> + <property name="geometry"> + <rect> + <x>200</x> + <y>103</y> + <width>50</width> + <height>51</height> + </rect> + </property> + <property name="maximum"> + <number>100</number> + </property> + <property name="notchesVisible"> + <bool>true</bool> + </property> + </widget> + <widget class="QLabel" name="lbFeedBack"> + <property name="geometry"> + <rect> + <x>60</x> + <y>30</y> + <width>71</width> + <height>20</height> + </rect> + </property> + <property name="text"> + <string>Feedback</string> + </property> + </widget> + <widget class="QSpinBox" name="sbFeedBack"> + <property name="geometry"> + <rect> + <x>60</x> + <y>50</y> + <width>51</width> + <height>21</height> + </rect> + </property> + <property name="maximum"> + <number>99</number> + </property> + </widget> + <widget class="QLabel" name="lbRate"> + <property name="geometry"> + <rect> + <x>140</x> + <y>30</y> + <width>51</width> + <height>20</height> + </rect> + </property> + <property name="text"> + <string>Rate</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + <widget class="QLabel" name="lbDepth"> + <property name="geometry"> + <rect> + <x>60</x> + <y>100</y> + <width>51</width> + <height>20</height> + </rect> + </property> + <property name="text"> + <string>Depth</string> + </property> + </widget> + <widget class="QLabel" name="lbLevelC"> + <property name="geometry"> + <rect> + <x>145</x> + <y>100</y> + <width>51</width> + <height>20</height> + </rect> + </property> + <property name="text"> + <string>Level</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + <widget class="QSpinBox" name="sbLevelC"> + <property name="geometry"> + <rect> + <x>140</x> + <y>120</y> + <width>56</width> + <height>21</height> + </rect> + </property> + <property name="maximum"> + <number>100</number> + </property> + </widget> + <widget class="QDoubleSpinBox" name="sbRate"> + <property name="geometry"> + <rect> + <x>137</x> + <y>50</y> + <width>61</width> + <height>21</height> + </rect> + </property> + <property name="minimum"> + <double>0.290000000000000</double> + </property> + <property name="maximum"> + <double>5.000000000000000</double> + </property> + <property name="singleStep"> + <double>0.100000000000000</double> + </property> + </widget> + <widget class="QLabel" name="lbLFO"> + <property name="geometry"> + <rect> + <x>35</x> + <y>77</y> + <width>41</width> + <height>20</height> + </rect> + </property> + <property name="text"> + <string>LFO</string> + </property> + </widget> + <widget class="QRadioButton" name="rbSine"> + <property name="geometry"> + <rect> + <x>70</x> + <y>77</y> + <width>61</width> + <height>20</height> + </rect> + </property> + <property name="text"> + <string>Sine</string> + </property> + </widget> + <widget class="QRadioButton" name="rbTriangle"> + <property name="geometry"> + <rect> + <x>145</x> + <y>77</y> + <width>91</width> + <height>20</height> + </rect> + </property> + <property name="text"> + <string>Trian&gle</string> + </property> + </widget> + <widget class="QDoubleSpinBox" name="sbDepth"> + <property name="geometry"> + <rect> + <x>60</x> + <y>120</y> + <width>51</width> + <height>21</height> + </rect> + </property> + <property name="decimals"> + <number>1</number> + </property> + <property name="maximum"> + <double>21.000000000000000</double> + </property> + <property name="singleStep"> + <double>0.100000000000000</double> + </property> + </widget> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/qmidiplayer-desktop/qmphelpwindow.cpp b/qmidiplayer-desktop/qmphelpwindow.cpp new file mode 100644 index 0000000..10cf083 --- /dev/null +++ b/qmidiplayer-desktop/qmphelpwindow.cpp @@ -0,0 +1,31 @@ +#include <fluidsynth.h> +#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-desktop/qmphelpwindow.hpp b/qmidiplayer-desktop/qmphelpwindow.hpp new file mode 100644 index 0000000..c2052b2 --- /dev/null +++ b/qmidiplayer-desktop/qmphelpwindow.hpp @@ -0,0 +1,26 @@ +#ifndef QMPHELPWINDOW_H +#define QMPHELPWINDOW_H + +#include <QDialog> +#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-desktop/qmphelpwindow.ui b/qmidiplayer-desktop/qmphelpwindow.ui new file mode 100644 index 0000000..fd21b5f --- /dev/null +++ b/qmidiplayer-desktop/qmphelpwindow.ui @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>qmpHelpWindow</class> + <widget class="QDialog" name="qmpHelpWindow"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>640</width> + <height>360</height> + </rect> + </property> + <property name="minimumSize"> + <size> + <width>640</width> + <height>360</height> + </size> + </property> + <property name="windowTitle"> + <string>Help</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QTextBrowser" name="textBrowser"> + <property name="openExternalLinks"> + <bool>true</bool> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/qmidiplayer-desktop/qmpimidimapper.hpp b/qmidiplayer-desktop/qmpimidimapper.hpp new file mode 100644 index 0000000..d35dbb9 --- /dev/null +++ b/qmidiplayer-desktop/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-desktop/qmpinfowindow.cpp b/qmidiplayer-desktop/qmpinfowindow.cpp new file mode 100644 index 0000000..689a756 --- /dev/null +++ b/qmidiplayer-desktop/qmpinfowindow.cpp @@ -0,0 +1,57 @@ +#include <QTextCodec> +#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-desktop/qmpinfowindow.hpp b/qmidiplayer-desktop/qmpinfowindow.hpp new file mode 100644 index 0000000..9a1e389 --- /dev/null +++ b/qmidiplayer-desktop/qmpinfowindow.hpp @@ -0,0 +1,24 @@ +#ifndef QMPINFOWINDOW_HPP +#define QMPINFOWINDOW_HPP + +#include <QDialog> + +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-desktop/qmpinfowindow.ui b/qmidiplayer-desktop/qmpinfowindow.ui new file mode 100644 index 0000000..664531a --- /dev/null +++ b/qmidiplayer-desktop/qmpinfowindow.ui @@ -0,0 +1,91 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>qmpInfoWindow</class> + <widget class="QDialog" name="qmpInfoWindow"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>400</width> + <height>142</height> + </rect> + </property> + <property name="minimumSize"> + <size> + <width>400</width> + <height>142</height> + </size> + </property> + <property name="windowTitle"> + <string>File Information</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QLabel" name="lbFileName"> + <property name="text"> + <string>File name: </string> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QLabel" name="lbTempo"> + <property name="text"> + <string>Tempo: </string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="lbKeySig"> + <property name="text"> + <string>Key Sig.: </string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="lbTimeSig"> + <property name="text"> + <string>Time Sig.:</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QLabel" name="lbTitle"> + <property name="text"> + <string>Title: </string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="lbCopyright"> + <property name="text"> + <string>Copyright: </string> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <widget class="QLabel" name="lbNoteCount"> + <property name="text"> + <string>Note count: </string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="lbFileStandard"> + <property name="text"> + <string>File standard: </string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/qmidiplayer-desktop/qmpmainwindow.cpp b/qmidiplayer-desktop/qmpmainwindow.cpp new file mode 100644 index 0000000..58caea1 --- /dev/null +++ b/qmidiplayer-desktop/qmpmainwindow.cpp @@ -0,0 +1,510 @@ +#include <cstdio> +#include <QUrl> +#include <QMimeData> +#include <QDirIterator> +#include <QDesktopWidget> +#include "qmpmainwindow.hpp" +#include "ui_qmpmainwindow.h" +#include "../core/qmpmidiplay.hpp" +#ifdef _WIN32 +#include <Windows.h> +#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;i<argc;++i) + { + if(argv[i][0]=='-') + { + if(!strcmp(argv[i],"--help")) + { + printf("Usage: %s [Options] [Midi Files]\n",argv[0]); + printf("Possible options are: \n"); + printf("-l, --load-all-files Load all files from the same folder.\n"); + printf("--help Show this help and exit.\n"); + printf("--version Show this version information and exit.\n"); + return 1; + } + if(!strcmp(argv[i],"--version")) + { + printf("QMidiPlayer %s\n",APP_VERSION); + return 1; + } + if(!strcmp(argv[i],"-l")||!strcmp(argv[i],"--load-all-files")) + loadfolder=true; + } + else + if(fluid_is_midifile(argv[i])) + { + if(!havemidi){havemidi=true;plistw->emptyList();} + 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<QUrl> l=event->mimeData()->urls(); + QStringList sl; + for(int i=0;i<l.size();++i) + sl.push_back(l.at(i).toLocalFile()); + plistw->insertItems(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<double> elapsed= + std::chrono::duration_cast<std::chrono::duration<double>>(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-desktop/qmpmainwindow.hpp b/qmidiplayer-desktop/qmpmainwindow.hpp new file mode 100644 index 0000000..a409d2e --- /dev/null +++ b/qmidiplayer-desktop/qmpmainwindow.hpp @@ -0,0 +1,90 @@ +#ifndef QMPMAINWINDOW_H +#define QMPMAINWINDOW_H + +#include <QMainWindow> +#include <QTimer> +#include <QCloseEvent> +#include <QMoveEvent> +#include <QDropEvent> +#include <QDragEnterEvent> +#include <QAction> +#include <QMenu> +#include <thread> +#include <chrono> +#include "../core/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-desktop/qmpmainwindow.ui b/qmidiplayer-desktop/qmpmainwindow.ui new file mode 100644 index 0000000..0764e09 --- /dev/null +++ b/qmidiplayer-desktop/qmpmainwindow.ui @@ -0,0 +1,413 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>qmpMainWindow</class> + <widget class="QMainWindow" name="qmpMainWindow"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>435</width> + <height>245</height> + </rect> + </property> + <property name="minimumSize"> + <size> + <width>435</width> + <height>245</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>435</width> + <height>245</height> + </size> + </property> + <property name="acceptDrops"> + <bool>true</bool> + </property> + <property name="windowTitle"> + <string>QMidiPlayer</string> + </property> + <property name="windowIcon"> + <iconset resource="resources.qrc"> + <normaloff>:/img/qmidiplyr.png</normaloff>:/img/qmidiplyr.png</iconset> + </property> + <widget class="QWidget" name="centralWidget"> + <widget class="QLabel" name="lbFileName"> + <property name="geometry"> + <rect> + <x>30</x> + <y>20</y> + <width>311</width> + <height>41</height> + </rect> + </property> + <property name="font"> + <font> + <pointsize>18</pointsize> + </font> + </property> + <property name="contextMenuPolicy"> + <enum>Qt::CustomContextMenu</enum> + </property> + <property name="text"> + <string>somefile.mid</string> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + <widget class="QSlider" name="hsTimer"> + <property name="geometry"> + <rect> + <x>20</x> + <y>90</y> + <width>321</width> + <height>20</height> + </rect> + </property> + <property name="maximum"> + <number>100</number> + </property> + <property name="pageStep"> + <number>0</number> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + <widget class="QPushButton" name="pbPlayPause"> + <property name="geometry"> + <rect> + <x>20</x> + <y>110</y> + <width>61</width> + <height>36</height> + </rect> + </property> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset resource="resources.qrc"> + <normaloff>:/img/play.png</normaloff>:/img/play.png</iconset> + </property> + <property name="iconSize"> + <size> + <width>32</width> + <height>32</height> + </size> + </property> + </widget> + <widget class="QPushButton" name="pbStop"> + <property name="geometry"> + <rect> + <x>80</x> + <y>110</y> + <width>61</width> + <height>36</height> + </rect> + </property> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset resource="resources.qrc"> + <normaloff>:/img/stop.png</normaloff>:/img/stop.png</iconset> + </property> + <property name="iconSize"> + <size> + <width>32</width> + <height>32</height> + </size> + </property> + </widget> + <widget class="QPushButton" name="pbPrev"> + <property name="geometry"> + <rect> + <x>140</x> + <y>110</y> + <width>61</width> + <height>36</height> + </rect> + </property> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset resource="resources.qrc"> + <normaloff>:/img/prev.png</normaloff>:/img/prev.png</iconset> + </property> + <property name="iconSize"> + <size> + <width>32</width> + <height>32</height> + </size> + </property> + </widget> + <widget class="QPushButton" name="pbNext"> + <property name="geometry"> + <rect> + <x>200</x> + <y>110</y> + <width>61</width> + <height>36</height> + </rect> + </property> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset resource="resources.qrc"> + <normaloff>:/img/next.png</normaloff>:/img/next.png</iconset> + </property> + <property name="iconSize"> + <size> + <width>32</width> + <height>32</height> + </size> + </property> + </widget> + <widget class="QPushButton" name="pbSettings"> + <property name="geometry"> + <rect> + <x>280</x> + <y>110</y> + <width>61</width> + <height>36</height> + </rect> + </property> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset resource="resources.qrc"> + <normaloff>:/img/settings.png</normaloff>:/img/settings.png</iconset> + </property> + <property name="iconSize"> + <size> + <width>32</width> + <height>32</height> + </size> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + </widget> + <widget class="QPushButton" name="pbChannels"> + <property name="geometry"> + <rect> + <x>20</x> + <y>160</y> + <width>151</width> + <height>36</height> + </rect> + </property> + <property name="styleSheet"> + <string notr="true">text-align:left</string> + </property> + <property name="text"> + <string>Channels</string> + </property> + <property name="icon"> + <iconset resource="resources.qrc"> + <normaloff>:/img/channel.png</normaloff>:/img/channel.png</iconset> + </property> + <property name="iconSize"> + <size> + <width>32</width> + <height>32</height> + </size> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + </widget> + <widget class="QPushButton" name="pbPList"> + <property name="geometry"> + <rect> + <x>190</x> + <y>160</y> + <width>151</width> + <height>36</height> + </rect> + </property> + <property name="styleSheet"> + <string notr="true">text-align:left</string> + </property> + <property name="text"> + <string>Playlist</string> + </property> + <property name="icon"> + <iconset resource="resources.qrc"> + <normaloff>:/img/list.png</normaloff>:/img/list.png</iconset> + </property> + <property name="iconSize"> + <size> + <width>32</width> + <height>32</height> + </size> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="checked"> + <bool>false</bool> + </property> + <property name="flat"> + <bool>false</bool> + </property> + </widget> + <widget class="QPushButton" name="pbEfx"> + <property name="geometry"> + <rect> + <x>20</x> + <y>200</y> + <width>151</width> + <height>36</height> + </rect> + </property> + <property name="styleSheet"> + <string notr="true">text-align:left</string> + </property> + <property name="text"> + <string>Effects</string> + </property> + <property name="icon"> + <iconset resource="resources.qrc"> + <normaloff>:/img/effects.png</normaloff>:/img/effects.png</iconset> + </property> + <property name="iconSize"> + <size> + <width>32</width> + <height>32</height> + </size> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + </widget> + <widget class="QPushButton" name="pbVisualization"> + <property name="geometry"> + <rect> + <x>190</x> + <y>200</y> + <width>151</width> + <height>36</height> + </rect> + </property> + <property name="styleSheet"> + <string notr="true">text-align:left</string> + </property> + <property name="text"> + <string>Visualization</string> + </property> + <property name="icon"> + <iconset resource="resources.qrc"> + <normaloff>:/img/visualization.png</normaloff>:/img/visualization.png</iconset> + </property> + <property name="iconSize"> + <size> + <width>32</width> + <height>32</height> + </size> + </property> + </widget> + <widget class="QLabel" name="lbPolyphone"> + <property name="geometry"> + <rect> + <x>320</x> + <y>20</y> + <width>111</width> + <height>20</height> + </rect> + </property> + <property name="text"> + <string><html><head/><body><p>Poly: 0/0</p></body></html></string> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + <widget class="QSlider" name="vsMasterVol"> + <property name="geometry"> + <rect> + <x>370</x> + <y>50</y> + <width>20</width> + <height>160</height> + </rect> + </property> + <property name="maximum"> + <number>100</number> + </property> + <property name="value"> + <number>50</number> + </property> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + </widget> + <widget class="QLabel" name="lbMasterVol"> + <property name="geometry"> + <rect> + <x>360</x> + <y>210</y> + <width>61</width> + <height>20</height> + </rect> + </property> + <property name="text"> + <string>Master</string> + </property> + </widget> + <widget class="QLabel" name="lbCurTime"> + <property name="geometry"> + <rect> + <x>20</x> + <y>70</y> + <width>66</width> + <height>20</height> + </rect> + </property> + <property name="text"> + <string>00:00</string> + </property> + </widget> + <widget class="QLabel" name="lbFinTime"> + <property name="geometry"> + <rect> + <x>270</x> + <y>70</y> + <width>66</width> + <height>20</height> + </rect> + </property> + <property name="text"> + <string>00:00</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + <widget class="QPushButton" name="pushButton"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>21</width> + <height>21</height> + </rect> + </property> + <property name="text"> + <string>?</string> + </property> + </widget> + </widget> + </widget> + <layoutdefault spacing="6" margin="11"/> + <resources> + <include location="resources.qrc"/> + </resources> + <connections/> +</ui> diff --git a/qmidiplayer-desktop/qmpplistwindow.cpp b/qmidiplayer-desktop/qmpplistwindow.cpp new file mode 100644 index 0000000..8f04fc1 --- /dev/null +++ b/qmidiplayer-desktop/qmpplistwindow.cpp @@ -0,0 +1,308 @@ +#include <cstdlib> +#include <ctime> +#include <QFileDialog> +#include <QDir> +#include <QDirIterator> +#include <QSettings> +#include <QUrl> +#include <QMimeData> +#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;i<ui->lwFiles->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<QUrl> l=event->mimeData()->urls(); + QStringList sl; + for(int i=0;i<l.size();++i) + sl.push_back(l.at(i).toLocalFile()); + insertItems(sl); +} +void qmpPlistWindow::dragEnterEvent(QDragEnterEvent *event) +{ + //if(event->mimeData()->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;i<sl.size();++i) + { + ui->lwFiles->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<QListWidgetItem*> sl=ui->lwFiles->selectedItems(); + for(int i=0;i<sl.size();++i) + { + ui->lwFiles->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;i<ui->lwFiles->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-desktop/qmpplistwindow.hpp b/qmidiplayer-desktop/qmpplistwindow.hpp new file mode 100644 index 0000000..6ceeb60 --- /dev/null +++ b/qmidiplayer-desktop/qmpplistwindow.hpp @@ -0,0 +1,57 @@ +#ifndef QMPPLISTWINDOW_H +#define QMPPLISTWINDOW_H + +#include <QDialog> +#include <QShowEvent> +#include <QCloseEvent> +#include <QMoveEvent> +#include <QDropEvent> +#include <QDragEnterEvent> +#include <QListWidgetItem> + +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-desktop/qmpplistwindow.ui b/qmidiplayer-desktop/qmpplistwindow.ui new file mode 100644 index 0000000..99124df --- /dev/null +++ b/qmidiplayer-desktop/qmpplistwindow.ui @@ -0,0 +1,263 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>qmpPlistWindow</class> + <widget class="QDialog" name="qmpPlistWindow"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>530</width> + <height>321</height> + </rect> + </property> + <property name="minimumSize"> + <size> + <width>530</width> + <height>321</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>530</width> + <height>321</height> + </size> + </property> + <property name="acceptDrops"> + <bool>true</bool> + </property> + <property name="windowTitle"> + <string>Playlist</string> + </property> + <widget class="QPushButton" name="pbAdd"> + <property name="geometry"> + <rect> + <x>10</x> + <y>280</y> + <width>121</width> + <height>36</height> + </rect> + </property> + <property name="styleSheet"> + <string notr="true">text-align:left</string> + </property> + <property name="text"> + <string>Add</string> + </property> + <property name="icon"> + <iconset resource="resources.qrc"> + <normaloff>:/img/add.png</normaloff>:/img/add.png</iconset> + </property> + <property name="iconSize"> + <size> + <width>32</width> + <height>32</height> + </size> + </property> + </widget> + <widget class="QPushButton" name="pbAddFolder"> + <property name="geometry"> + <rect> + <x>140</x> + <y>280</y> + <width>121</width> + <height>36</height> + </rect> + </property> + <property name="styleSheet"> + <string notr="true">text-align:left</string> + </property> + <property name="text"> + <string>Add Folder</string> + </property> + <property name="icon"> + <iconset resource="resources.qrc"> + <normaloff>:/img/addfolder.png</normaloff>:/img/addfolder.png</iconset> + </property> + <property name="iconSize"> + <size> + <width>32</width> + <height>32</height> + </size> + </property> + </widget> + <widget class="QPushButton" name="pbRepeat"> + <property name="geometry"> + <rect> + <x>270</x> + <y>240</y> + <width>121</width> + <height>36</height> + </rect> + </property> + <property name="styleSheet"> + <string notr="true">text-align:left</string> + </property> + <property name="text"> + <string>Repeat Off</string> + </property> + <property name="icon"> + <iconset resource="resources.qrc"> + <normaloff>:/img/repeat-non.png</normaloff>:/img/repeat-non.png</iconset> + </property> + <property name="iconSize"> + <size> + <width>32</width> + <height>32</height> + </size> + </property> + </widget> + <widget class="QPushButton" name="pbShuffle"> + <property name="geometry"> + <rect> + <x>400</x> + <y>240</y> + <width>121</width> + <height>36</height> + </rect> + </property> + <property name="styleSheet"> + <string notr="true">text-align:left</string> + </property> + <property name="text"> + <string>Shuffle Off</string> + </property> + <property name="icon"> + <iconset resource="resources.qrc"> + <normaloff>:/img/shuffle-off.png</normaloff>:/img/shuffle-off.png</iconset> + </property> + <property name="iconSize"> + <size> + <width>32</width> + <height>32</height> + </size> + </property> + </widget> + <widget class="QPushButton" name="pbSave"> + <property name="geometry"> + <rect> + <x>10</x> + <y>240</y> + <width>121</width> + <height>36</height> + </rect> + </property> + <property name="styleSheet"> + <string notr="true">text-align:left</string> + </property> + <property name="text"> + <string>Save</string> + </property> + <property name="icon"> + <iconset resource="resources.qrc"> + <normaloff>:/img/save.png</normaloff>:/img/save.png</iconset> + </property> + <property name="iconSize"> + <size> + <width>32</width> + <height>32</height> + </size> + </property> + </widget> + <widget class="QPushButton" name="pbLoad"> + <property name="geometry"> + <rect> + <x>140</x> + <y>240</y> + <width>121</width> + <height>36</height> + </rect> + </property> + <property name="styleSheet"> + <string notr="true">text-align:left</string> + </property> + <property name="text"> + <string>Load</string> + </property> + <property name="icon"> + <iconset resource="resources.qrc"> + <normaloff>:/img/load.png</normaloff>:/img/load.png</iconset> + </property> + <property name="iconSize"> + <size> + <width>32</width> + <height>32</height> + </size> + </property> + </widget> + <widget class="QPushButton" name="pbRemove"> + <property name="geometry"> + <rect> + <x>270</x> + <y>280</y> + <width>121</width> + <height>36</height> + </rect> + </property> + <property name="styleSheet"> + <string notr="true">text-align:left</string> + </property> + <property name="text"> + <string>Remove</string> + </property> + <property name="icon"> + <iconset resource="resources.qrc"> + <normaloff>:/img/remove.png</normaloff>:/img/remove.png</iconset> + </property> + <property name="iconSize"> + <size> + <width>32</width> + <height>32</height> + </size> + </property> + </widget> + <widget class="QPushButton" name="pbClear"> + <property name="geometry"> + <rect> + <x>400</x> + <y>280</y> + <width>121</width> + <height>36</height> + </rect> + </property> + <property name="styleSheet"> + <string notr="true">text-align:left</string> + </property> + <property name="text"> + <string>Clear</string> + </property> + <property name="icon"> + <iconset resource="resources.qrc"> + <normaloff>:/img/clear.png</normaloff>:/img/clear.png</iconset> + </property> + <property name="iconSize"> + <size> + <width>32</width> + <height>32</height> + </size> + </property> + </widget> + <widget class="QListWidget" name="lwFiles"> + <property name="geometry"> + <rect> + <x>10</x> + <y>10</y> + <width>511</width> + <height>221</height> + </rect> + </property> + <property name="acceptDrops"> + <bool>false</bool> + </property> + <property name="dragEnabled"> + <bool>true</bool> + </property> + <property name="dragDropMode"> + <enum>QAbstractItemView::InternalMove</enum> + </property> + </widget> + </widget> + <resources> + <include location="resources.qrc"/> + </resources> + <connections/> +</ui> diff --git a/qmidiplayer-desktop/qmppresetselect.cpp b/qmidiplayer-desktop/qmppresetselect.cpp new file mode 100644 index 0000000..be589c5 --- /dev/null +++ b/qmidiplayer-desktop/qmppresetselect.cpp @@ -0,0 +1,99 @@ +#include <cstdio> +#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;i<ui->lwBankSelect->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-desktop/qmppresetselect.hpp b/qmidiplayer-desktop/qmppresetselect.hpp new file mode 100644 index 0000000..54f5764 --- /dev/null +++ b/qmidiplayer-desktop/qmppresetselect.hpp @@ -0,0 +1,36 @@ +#ifndef QMPPRESETSELECT_H +#define QMPPRESETSELECT_H + +#include <QDialog> +#include <QShowEvent> + +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-desktop/qmppresetselect.ui b/qmidiplayer-desktop/qmppresetselect.ui new file mode 100644 index 0000000..f18600d --- /dev/null +++ b/qmidiplayer-desktop/qmppresetselect.ui @@ -0,0 +1,106 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>qmpPresetSelector</class> + <widget class="QDialog" name="qmpPresetSelector"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>404</width> + <height>300</height> + </rect> + </property> + <property name="minimumSize"> + <size> + <width>404</width> + <height>300</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>404</width> + <height>300</height> + </size> + </property> + <property name="windowTitle"> + <string>Preset Selection</string> + </property> + <property name="modal"> + <bool>true</bool> + </property> + <widget class="QListWidget" name="lwBankSelect"> + <property name="geometry"> + <rect> + <x>10</x> + <y>30</y> + <width>71</width> + <height>221</height> + </rect> + </property> + </widget> + <widget class="QListWidget" name="lwPresetSelect"> + <property name="geometry"> + <rect> + <x>90</x> + <y>30</y> + <width>301</width> + <height>221</height> + </rect> + </property> + </widget> + <widget class="QLabel" name="lbBnk"> + <property name="geometry"> + <rect> + <x>10</x> + <y>10</y> + <width>66</width> + <height>20</height> + </rect> + </property> + <property name="text"> + <string>Bank</string> + </property> + </widget> + <widget class="QLabel" name="lbPst"> + <property name="geometry"> + <rect> + <x>90</x> + <y>10</y> + <width>66</width> + <height>20</height> + </rect> + </property> + <property name="text"> + <string>Preset</string> + </property> + </widget> + <widget class="QPushButton" name="pbOk"> + <property name="geometry"> + <rect> + <x>300</x> + <y>260</y> + <width>97</width> + <height>36</height> + </rect> + </property> + <property name="text"> + <string>OK</string> + </property> + </widget> + <widget class="QPushButton" name="pbCancel"> + <property name="geometry"> + <rect> + <x>190</x> + <y>260</y> + <width>97</width> + <height>36</height> + </rect> + </property> + <property name="text"> + <string>Cancel</string> + </property> + </widget> + </widget> + <resources/> + <connections/> +</ui> diff --git a/qmidiplayer-desktop/qmpsettingswindow.cpp b/qmidiplayer-desktop/qmpsettingswindow.cpp new file mode 100644 index 0000000..c2e31a2 --- /dev/null +++ b/qmidiplayer-desktop/qmpsettingswindow.cpp @@ -0,0 +1,289 @@ +#include <QFileDialog> +#include <QDir> +#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;i<ui->cbEncoding->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;i<ui->cbAudioDrv->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;i<ui->cbBufSize->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;i<ui->cbBufCnt->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;i<ui->cbFormat->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;i<ui->cbFrequency->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;i<ui->cbBSMode->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;i<ui->lwSoundfont->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;i<sl.size();++i) + { + ui->lwSoundfont->addItem(new QListWidgetItem(sl.at(i))); + } +} + +void qmpSettingsWindow::on_pbRemove_clicked() +{ + QList<QListWidgetItem*> sl=ui->lwSoundfont->selectedItems(); + for(int i=0;i<sl.size();++i) + { + ui->lwSoundfont->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-desktop/qmpsettingswindow.hpp b/qmidiplayer-desktop/qmpsettingswindow.hpp new file mode 100644 index 0000000..c506de4 --- /dev/null +++ b/qmidiplayer-desktop/qmpsettingswindow.hpp @@ -0,0 +1,47 @@ +#ifndef QMPSETTINGSWINDOW_H +#define QMPSETTINGSWINDOW_H + +#include <QDialog> +#include <QCloseEvent> +#include <QSettings> +#include <QListWidget> + +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-desktop/qmpsettingswindow.ui b/qmidiplayer-desktop/qmpsettingswindow.ui new file mode 100644 index 0000000..330afa2 --- /dev/null +++ b/qmidiplayer-desktop/qmpsettingswindow.ui @@ -0,0 +1,761 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>qmpSettingsWindow</class> + <widget class="QDialog" name="qmpSettingsWindow"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>494</width> + <height>445</height> + </rect> + </property> + <property name="minimumSize"> + <size> + <width>494</width> + <height>445</height> + </size> + </property> + <property name="windowTitle"> + <string>Settings</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QTabWidget" name="tabWidget"> + <property name="currentIndex"> + <number>0</number> + </property> + <widget class="QWidget" name="tab"> + <attribute name="title"> + <string>Midi</string> + </attribute> + <layout class="QVBoxLayout" name="verticalLayout_4"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_6"> + <item> + <widget class="QLabel" name="lbOutputDevice"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Default Output Device</string> + </property> + </widget> + </item> + <item> + <widget class="QComboBox" name="cbOutputDevice"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <item> + <property name="text"> + <string>Internal FluidSynth</string> + </property> + </item> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QCheckBox" name="cbDisableMapping"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Disable Midi Mapping</string> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="cbSendSysx"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Send SysEx</string> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="cbWaitVoice"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Wait for remaining voices before stopping</string> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_7"> + <item> + <widget class="QLabel" name="lbEncoding"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Text Encoding</string> + </property> + </widget> + </item> + <item> + <widget class="QComboBox" name="cbEncoding"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <item> + <property name="text"> + <string>Unicode</string> + </property> + </item> + <item> + <property name="text"> + <string>Big5</string> + </property> + </item> + <item> + <property name="text"> + <string>Big5-HKSCS</string> + </property> + </item> + <item> + <property name="text"> + <string>CP949</string> + </property> + </item> + <item> + <property name="text"> + <string>EUC-JP</string> + </property> + </item> + <item> + <property name="text"> + <string>EUC-KR</string> + </property> + </item> + <item> + <property name="text"> + <string>GB18030</string> + </property> + </item> + <item> + <property name="text"> + <string>KOI8-R</string> + </property> + </item> + <item> + <property name="text"> + <string>KOI8-U</string> + </property> + </item> + <item> + <property name="text"> + <string>Macintosh</string> + </property> + </item> + <item> + <property name="text"> + <string>Shift-JIS</string> + </property> + </item> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <widget class="QWidget" name="tab_2"> + <attribute name="title"> + <string>Synth</string> + </attribute> + <layout class="QGridLayout" name="gridLayout_2"> + <item row="2" column="0"> + <widget class="QLabel" name="lbBufCnt"> + <property name="text"> + <string>Audio Buffer Count</string> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="lbBufSize"> + <property name="text"> + <string>Audio Buffer Size</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QComboBox" name="cbBufSize"> + <property name="editable"> + <bool>true</bool> + </property> + <property name="currentIndex"> + <number>1</number> + </property> + <item> + <property name="text"> + <string>64</string> + </property> + </item> + <item> + <property name="text"> + <string>128</string> + </property> + </item> + <item> + <property name="text"> + <string>256</string> + </property> + </item> + <item> + <property name="text"> + <string>512</string> + </property> + </item> + <item> + <property name="text"> + <string>1024</string> + </property> + </item> + <item> + <property name="text"> + <string>2048</string> + </property> + </item> + <item> + <property name="text"> + <string>4096</string> + </property> + </item> + <item> + <property name="text"> + <string>8192</string> + </property> + </item> + </widget> + </item> + <item row="4" column="0"> + <widget class="QLabel" name="lbFrequency"> + <property name="text"> + <string>Audio Frequency</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QComboBox" name="cbBufCnt"> + <property name="editable"> + <bool>true</bool> + </property> + <item> + <property name="text"> + <string>2</string> + </property> + </item> + <item> + <property name="text"> + <string>4</string> + </property> + </item> + <item> + <property name="text"> + <string>8</string> + </property> + </item> + <item> + <property name="text"> + <string>16</string> + </property> + </item> + <item> + <property name="text"> + <string>32</string> + </property> + </item> + <item> + <property name="text"> + <string>64</string> + </property> + </item> + </widget> + </item> + <item row="0" column="0"> + <widget class="QLabel" name="lbAudioDrv"> + <property name="text"> + <string>Audio Driver</string> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="QComboBox" name="cbFormat"> + <item> + <property name="text"> + <string>16bits</string> + </property> + </item> + <item> + <property name="text"> + <string>float</string> + </property> + </item> + </widget> + </item> + <item row="0" column="1"> + <widget class="QComboBox" name="cbAudioDrv"/> + </item> + <item row="4" column="1"> + <widget class="QComboBox" name="cbFrequency"> + <property name="currentIndex"> + <number>2</number> + </property> + <item> + <property name="text"> + <string>22050</string> + </property> + </item> + <item> + <property name="text"> + <string>44100</string> + </property> + </item> + <item> + <property name="text"> + <string>48000</string> + </property> + </item> + <item> + <property name="text"> + <string>96000</string> + </property> + </item> + </widget> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="lbFormat"> + <property name="text"> + <string>Audio Format</string> + </property> + </widget> + </item> + <item row="5" column="1"> + <widget class="QSpinBox" name="sbPolyphony"> + <property name="minimum"> + <number>1</number> + </property> + <property name="maximum"> + <number>65535</number> + </property> + <property name="value"> + <number>2048</number> + </property> + </widget> + </item> + <item row="5" column="0"> + <widget class="QLabel" name="lbPolyphony"> + <property name="text"> + <string>Max Polyphony</string> + </property> + </widget> + </item> + <item row="7" column="0"> + <widget class="QCheckBox" name="cbAutoBS"> + <property name="text"> + <string>Auto bank select mode</string> + </property> + </widget> + </item> + <item row="8" column="0"> + <widget class="QLabel" name="lbBSMode"> + <property name="text"> + <string>Bank select mode</string> + </property> + </widget> + </item> + <item row="8" column="1"> + <widget class="QComboBox" name="cbBSMode"> + <property name="currentIndex"> + <number>1</number> + </property> + <item> + <property name="text"> + <string>Ignored</string> + </property> + </item> + <item> + <property name="text"> + <string>CC#0</string> + </property> + </item> + <item> + <property name="text"> + <string>CC#32</string> + </property> + </item> + <item> + <property name="text"> + <string>CC#0*128+CC#32</string> + </property> + </item> + </widget> + </item> + <item row="6" column="0"> + <widget class="QLabel" name="lbCPUCores"> + <property name="text"> + <string>CPU Cores</string> + </property> + </widget> + </item> + <item row="6" column="1"> + <widget class="QSpinBox" name="sbCPUCores"> + <property name="minimum"> + <number>1</number> + </property> + <property name="maximum"> + <number>256</number> + </property> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" name="tab_3"> + <attribute name="title"> + <string>Soundfonts</string> + </attribute> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <widget class="QListWidget" name="lwSoundfont"> + <property name="dragDropMode"> + <enum>QAbstractItemView::InternalMove</enum> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QPushButton" name="pbAdd"> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset resource="resources.qrc"> + <normaloff>:/img/add.png</normaloff>:/img/add.png</iconset> + </property> + <property name="iconSize"> + <size> + <width>24</width> + <height>24</height> + </size> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="pbRemove"> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset resource="resources.qrc"> + <normaloff>:/img/remove.png</normaloff>:/img/remove.png</iconset> + </property> + <property name="iconSize"> + <size> + <width>24</width> + <height>24</height> + </size> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="pbUp"> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset resource="resources.qrc"> + <normaloff>:/img/up.png</normaloff>:/img/up.png</iconset> + </property> + <property name="iconSize"> + <size> + <width>24</width> + <height>24</height> + </size> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="pbDown"> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset resource="resources.qrc"> + <normaloff>:/img/down.png</normaloff>:/img/down.png</iconset> + </property> + <property name="iconSize"> + <size> + <width>24</width> + <height>24</height> + </size> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <widget class="QWidget" name="tab_4"> + <attribute name="title"> + <string>Behavior</string> + </attribute> + <layout class="QVBoxLayout" name="verticalLayout_3"> + <item> + <widget class="QCheckBox" name="cbRestorePlaylist"> + <property name="text"> + <string>Restore last playlist on startup</string> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="cbLoadFolder"> + <property name="text"> + <string>Load files in the same folder</string> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="cbDialogStatus"> + <property name="text"> + <string>Save dialog status</string> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="cbSaveEfxParam"> + <property name="text"> + <string>Save parameters in effects window</string> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="cbPersistentfs"> + <property name="text"> + <string>Persistent fluidsynth instance</string> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <widget class="QLabel" name="lbVisualMode"> + <property name="text"> + <string>Visualization Mode</string> + </property> + </widget> + </item> + <item> + <widget class="QComboBox" name="cbVisualMode"/> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_3"> + <item> + <widget class="QLabel" name="lbViewDist"> + <property name="text"> + <string>View distance</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Expanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>50</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QSlider" name="hsViewDist"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>60</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="sbViewDist"/> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_4"> + <item> + <widget class="QLabel" name="lbNoteStretch"> + <property name="text"> + <string>Note stretch</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Expanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>60</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QSlider" name="hsNoteStretch"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>60</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="sbNoteStretch"/> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_5"> + <item> + <widget class="QLabel" name="lbFog"> + <property name="text"> + <string>Fog Start</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_3"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Expanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>82</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QSlider" name="hsFog"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>60</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="sbFog"/> + </item> + </layout> + </item> + </layout> + </widget> + </widget> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <resources> + <include location="resources.qrc"/> + </resources> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>qmpSettingsWindow</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>qmpSettingsWindow</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/qmidiplayer-desktop/resources.qrc b/qmidiplayer-desktop/resources.qrc new file mode 100644 index 0000000..351d2fa --- /dev/null +++ b/qmidiplayer-desktop/resources.qrc @@ -0,0 +1,36 @@ +<RCC> + <qresource prefix="/"> + <file>../img/add.png</file> + <file>../img/list.png</file> + <file>../img/addfolder.png</file> + <file>../img/channel.png</file> + <file>../img/prev.png</file> + <file>../img/qmidiplyr.png</file> + <file>../img/remove.png</file> + <file>../img/clear.png</file> + <file>../img/down.png</file> + <file>../img/effects.png</file> + <file>../img/repeat-all.png</file> + <file>../img/repeat-base.png</file> + <file>../img/repeat-non.png</file> + <file>../img/load.png</file> + <file>../img/next.png</file> + <file>../img/repeat-one.png</file> + <file>../img/save.png</file> + <file>../img/settings.png</file> + <file>../img/pause.png</file> + <file>../img/play.png</file> + <file>../img/shuffle-off.png</file> + <file>../img/shuffle.png</file> + <file>../img/stop.png</file> + <file>../img/up.png</file> + <file>../img/visualization.png</file> + <file>../img/mainw.png</file> + <file>../img/chanw.png</file> + <file>../doc/index.html</file> + <file>../doc/version.html</file> + <file>../doc/license.html</file> + <file>../doc/mainwindow.html</file> + <file>../doc/channeldialog.html</file> + </qresource> +</RCC> diff --git a/qmidiplayer-lite/deployment.pri b/qmidiplayer-lite/deployment.pri new file mode 100644 index 0000000..57bdd3a --- /dev/null +++ b/qmidiplayer-lite/deployment.pri @@ -0,0 +1,13 @@ +unix:!android { + isEmpty(target.path) { + qnx { + target.path = /tmp/$${TARGET}/bin + } else { + target.path = /usr/bin + } + export(target.path) + } + INSTALLS += target +} + +export(INSTALLS) diff --git a/qmidiplayer-lite/main.cpp b/qmidiplayer-lite/main.cpp new file mode 100644 index 0000000..1a87b33 --- /dev/null +++ b/qmidiplayer-lite/main.cpp @@ -0,0 +1,15 @@ +#include <QApplication> +#include <QtQml> +#include <QQmlApplicationEngine> +#include "qmpcorewrapper.hpp" + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + qmlRegisterType<CQMPCoreWrapper>("org.chrisoft.qmpcore",1,0,"CQMPCoreWrapper"); + + QQmlApplicationEngine engine; + engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); + + return app.exec(); +} diff --git a/qmidiplayer-lite/main.qml b/qmidiplayer-lite/main.qml new file mode 100644 index 0000000..0ec0975 --- /dev/null +++ b/qmidiplayer-lite/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/qmidiplayer-lite/qmidiplayer-lite.pro b/qmidiplayer-lite/qmidiplayer-lite.pro new file mode 100644 index 0000000..9fb8712 --- /dev/null +++ b/qmidiplayer-lite/qmidiplayer-lite.pro @@ -0,0 +1,24 @@ +TEMPLATE = app + +QT += qml quick +unix:QT += widgets +win32:QT += widgets +CONFIG += c++11 + +SOURCES += main.cpp \ + ../core/qmpmidiplay.cpp \ + ../core/qmpmidiread.cpp + +RESOURCES += qml.qrc + +# Additional import path used to resolve QML modules in Qt Creator's code model +QML_IMPORT_PATH = + +# Default rules for deployment. +include(deployment.pri) + +HEADERS += \ + ../core/qmpmidiplay.hpp \ + qmpcorewrapper.hpp + +LIBS += -lfluidsynth diff --git a/qmidiplayer-lite/qml.qrc b/qmidiplayer-lite/qml.qrc new file mode 100644 index 0000000..5f6483a --- /dev/null +++ b/qmidiplayer-lite/qml.qrc @@ -0,0 +1,5 @@ +<RCC> + <qresource prefix="/"> + <file>main.qml</file> + </qresource> +</RCC> diff --git a/qmidiplayer-lite/qmpcorewrapper.hpp b/qmidiplayer-lite/qmpcorewrapper.hpp new file mode 100644 index 0000000..ed024df --- /dev/null +++ b/qmidiplayer-lite/qmpcorewrapper.hpp @@ -0,0 +1,58 @@ +#ifndef QMPCOREWRAPPER_H +#define QMPCOREWRAPPER_H +#include <QObject> +#include <QUrl> +#include <thread> +#include <fluidsynth.h> +#include "../core/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/qmidiplayer-lite/qmpmidiplay.cpp b/qmidiplayer-lite/qmpmidiplay.cpp new file mode 100644 index 0000000..baec9a2 --- /dev/null +++ b/qmidiplayer-lite/qmpmidiplay.cpp @@ -0,0 +1,406 @@ +#include <cstdio> +#include <chrono> +#include <thread> +#include <fluidsynth.h> +#include "qmpmidiplay.hpp" +#ifdef _WIN32 +#include <windows.h> +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)*1000000<t*pf); +} +#endif +void CMidiPlayer::playEvents() +{ + for(uint32_t ct=midiFile->getEvent(0)->time;tceptr<midiFile->getEventCount();) + { + while(tcpaused)std::this_thread::sleep_for(std::chrono::milliseconds(100)); + while(!tcstop&&midiFile&&tceptr<midiFile->getEventCount()&&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;eptr<midiFile->getEventCount();) + { + while(eptr<midiFile->getEventCount()&&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;eptr<midiFile->getEventCount();) + { + while(eptr<midiFile->getEventCount()&&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<<bn);} +void CMidiPlayer::setMute(int ch,bool m) +{setBit(mute,ch,m?1:0);} +void CMidiPlayer::setSolo(int ch,bool s) +{setBit(solo,ch,s?1:0);} +int CMidiPlayer::getCC(int ch, int id) +{int ret=0;synth?fluid_synth_get_cc(synth,ch,id,&ret):0;return ret;} +void CMidiPlayer::setCC(int ch, int id, int val) +{synth?fluid_synth_cc(synth,ch,id,val):0;} +void CMidiPlayer::getReverbPara(double *r,double *d,double *w,double *l) +{ + if(!synth)return; + *r=fluid_synth_get_reverb_roomsize(synth); + *d=fluid_synth_get_reverb_damp(synth); + *w=fluid_synth_get_reverb_width(synth); + *l=fluid_synth_get_reverb_level(synth); +} +void CMidiPlayer::setReverbPara(int e,double r,double d,double w,double l) +{ + if(!synth)return; + fluid_synth_set_reverb_on(synth,e); + fluid_synth_set_reverb(synth,r,d,w,l); +} +void CMidiPlayer::getChorusPara(int *fb,double *l,double *r,double *d,int *type) +{ + if(!synth)return; + *fb=fluid_synth_get_chorus_nr(synth); + *l=fluid_synth_get_chorus_level(synth); + *r=fluid_synth_get_chorus_speed_Hz(synth); + *d=fluid_synth_get_chorus_depth_ms(synth); + *type=fluid_synth_get_chorus_type(synth); +} +void CMidiPlayer::setChorusPara(int e,int fb,double l,double r,double d,int type) +{ + if(!synth)return; + fluid_synth_set_chorus_on(synth,e); + fluid_synth_set_chorus(synth,fb,l,r,d,type); +} +fluid_settings_t* CMidiPlayer::getFluidSettings(){return settings;} +void CMidiPlayer::pushSoundFont(const char *sf) +{fluid_synth_sfload(synth,sf,1);} +int CMidiPlayer::getSFCount() +{return synth?fluid_synth_sfcount(synth):0;} +fluid_sfont_t* CMidiPlayer::getSFPtr(int sfid) +{return synth&&sfid<getSFCount()?fluid_synth_get_sfont(synth,sfid):NULL;} diff --git a/qmidiplayer-lite/qmpmidiplay.hpp b/qmidiplayer-lite/qmpmidiplay.hpp new file mode 100644 index 0000000..fafd677 --- /dev/null +++ b/qmidiplayer-lite/qmpmidiplay.hpp @@ -0,0 +1,137 @@ +//sorry for the stupid C-like code... +#ifndef QMPMIDIPLAY_H +#define QMPMIDIPLAY_H +#include <cstring> +#include <cstdint> +#include <cstdlib> +#include <fluidsynth.h> +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/qmidiplayer-lite/qmpmidiread.cpp b/qmidiplayer-lite/qmpmidiread.cpp new file mode 100644 index 0000000..0bcf597 --- /dev/null +++ b/qmidiplayer-lite/qmpmidiread.cpp @@ -0,0 +1,240 @@ +//CLI Midi file player based on libfluidsynth +//Midi file reading module +//Written by Chris Xiong, 2015 +#include <cstdio> +#include <cstring> +#include <cstdlib> +#include <cstdint> +#include <cstdarg> +#include <algorithm> +#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->time<b->time:a->iid<b->iid;} +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;c<len;++c) + { + ++byteread;if(str)str[c]=fgetc(f);else fgetc(f); + } + if(str)str[c]='\0';eventList[eventc++]=new SEvent(curid,curt,type,metatype,0,str); + if(str&&metatype==0x03&&!title) + { + title=new char[len+8]; + strcpy(title,str); + } + if(str&&metatype==0x02&&!copyright) + { + copyright=new char[len+8]; + strcpy(copyright,str); + } + if(len<=1024&&len>0)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;c<len;++c){++byteread;str[c]=fgetc(f);} + } + else for(c=0;c<len;++c){++byteread;str[c]=fgetc(f);} + eventList[eventc++]=new SEvent(curid,curt,type,len,0,str); + if(!strcmp(str,GM1SysX))std=1; + if(!strcmp(str,GM2SysX))std=2; + if(!strcmp(str,GSSysEx))std=3; + if(!strcmp(str,XGSysEx))std=4; + } + else error(0,"W: Unknown event type %#x",type); + break; + default: + fseek(f,-1,SEEK_CUR);--byteread;type=lasttype;goto retry; + } + lasttype=type;++curid; + return 1; +} +void CMidiFile::trackChunkReader() +{ + int chnklen=readDW();byteread=0;curt=0;curid=0; + while(/*byteread<chnklen&&*/eventReader()); + if(byteread<chnklen) + { + error(0,"W: Extra bytes after EOT event."); + while(byteread<chnklen){fgetc(f);++byteread;} + } + /*if(byteread>chnklen) + { + 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(;byteread<chnklen;++byteread){fgetc(f);} +} +int CMidiFile::chunkReader(int hdrXp) +{ + char hdr[6]; + if(!fgets(hdr,5,f))error(1,"E: Unexpected EOF."); + if(hdrXp) + if(strncmp(hdr,"MThd",4)){error(1,"E: Wrong MIDI header.");throw;} + else return headerChunkReader(),0; + else + if(strncmp(hdr,"MTrk",4)) + { + error(0,"W: Wrong track chunk header. Ignoring the whole chunk."); + for(int chnklen=readDW();chnklen>0;--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<trk;i+=chunkReader(0)); + printf("%d note(s)\n",notes); + fclose(f); + std::sort(eventList,eventList+eventc,cmp); + } + catch(int){fprintf(stderr,"E: %s is not a supported file.\n",fn);valid=0;} +} +CMidiFile::~CMidiFile() +{ + for(uint32_t i=0;i<eventc;++i)delete eventList[i]; + if(title)delete[] title;if(copyright)delete[] copyright; +} +const SEvent* CMidiFile::getEvent(uint32_t id){return id<eventc?eventList[id]:NULL;} +uint32_t CMidiFile::getEventCount(){return eventc;} +uint32_t CMidiFile::getDivision(){return divs;} +uint32_t CMidiFile::getNoteCount(){return notes;} +uint32_t CMidiFile::getStandard(){return std;} +bool CMidiFile::isValid(){return valid;} +const char* CMidiFile::getTitle(){return title;} +const char* CMidiFile::getCopyright(){return copyright;} diff --git a/qmidiplayer.pro b/qmidiplayer.pro index 63e20b6..da362f3 100644 --- a/qmidiplayer.pro +++ b/qmidiplayer.pro @@ -1,64 +1,5 @@ -#------------------------------------------------- -# -# Project created by QtCreator 2015-12-25T20:24:49 -# -#------------------------------------------------- +TEMPLATE = subdirs -QT += core gui - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets - -TARGET = qmidiplayer -TEMPLATE = app - - -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 += ./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 += ./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) { - PREFIX = /usr/local - } - BINDIR = $$PREFIX/bin - target.path = $$BINDIR - INSTALLS += target - QMAKE_CXXFLAGS += -std=c++11 -Wall - LIBS += -lfluidsynth -} -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 +SUBDIRS = \ + qmidiplayer-desktop \ + qmidiplayer-lite diff --git a/qmidiplayer.src.d/main.cpp b/qmidiplayer.src.d/main.cpp deleted file mode 100644 index c9f3b42..0000000 --- a/qmidiplayer.src.d/main.cpp +++ /dev/null @@ -1,29 +0,0 @@ -/* - *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 <http://www.gnu.org/licenses/>. - */ -#include "qmpmainwindow.hpp" -#include <QApplication> -#include <QStyle> - -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 deleted file mode 100644 index 7c181a0..0000000 --- a/qmidiplayer.src.d/qdialskulpturestyle.cpp +++ /dev/null @@ -1,437 +0,0 @@ -/****************************************************************************** - - Skulpture - Classical Three-Dimensional Artwork for Qt 4 - - Copyright (c) 2007-2009 Christoph Feck <christoph@maxiom.de> - - 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 <cmath> -#include <QStyleOptionSlider> -#include <QPixmapCache> -#include <QPainter> - -#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<const QStyleOptionSlider *>(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<const QAbstractSlider *>(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 deleted file mode 100644 index 2f3ba04..0000000 --- a/qmidiplayer.src.d/qdialskulpturestyle.hpp +++ /dev/null @@ -1,39 +0,0 @@ -/****************************************************************************** - - Skulpture - Classical Three-Dimensional Artwork for Qt 4 - - Copyright (c) 2007-2009 Christoph Feck <christoph@maxiom.de> - - 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 <QCommonStyle> - -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 deleted file mode 100644 index f1d4e5e..0000000 --- a/qmidiplayer.src.d/qmpchanneleditor.cpp +++ /dev/null @@ -1,193 +0,0 @@ -#include <cstdio> -#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<QDial*> dials=findChildren<QDial*>(); - for(int i=0;i<dials.count();++i) - dials.at(i)->setStyle(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 deleted file mode 100644 index 0653af5..0000000 --- a/qmidiplayer.src.d/qmpchanneleditor.hpp +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef QMPCHANNELEDITOR_H -#define QMPCHANNELEDITOR_H - -#include <QDialog> -#include <QShowEvent> -#include <QCloseEvent> -#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 deleted file mode 100644 index 49e8c8e..0000000 --- a/qmidiplayer.src.d/qmpchanneleditor.ui +++ /dev/null @@ -1,602 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>qmpChannelEditor</class> - <widget class="QDialog" name="qmpChannelEditor"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>422</width> - <height>300</height> - </rect> - </property> - <property name="minimumSize"> - <size> - <width>422</width> - <height>300</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>422</width> - <height>300</height> - </size> - </property> - <property name="windowTitle"> - <string>Dialog</string> - </property> - <widget class="QPushButton" name="pbChLeft"> - <property name="geometry"> - <rect> - <x>10</x> - <y>10</y> - <width>21</width> - <height>21</height> - </rect> - </property> - <property name="text"> - <string><</string> - </property> - </widget> - <widget class="QLabel" name="lbChannelNumber"> - <property name="geometry"> - <rect> - <x>30</x> - <y>10</y> - <width>21</width> - <height>20</height> - </rect> - </property> - <property name="text"> - <string>1</string> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - </widget> - <widget class="QPushButton" name="pbChRight"> - <property name="geometry"> - <rect> - <x>50</x> - <y>10</y> - <width>21</width> - <height>21</height> - </rect> - </property> - <property name="text"> - <string>></string> - </property> - </widget> - <widget class="QLabel" name="lbPresetName"> - <property name="geometry"> - <rect> - <x>90</x> - <y>10</y> - <width>261</width> - <height>51</height> - </rect> - </property> - <property name="font"> - <font> - <pointsize>16</pointsize> - </font> - </property> - <property name="text"> - <string>Yamaha Grand Piano</string> - </property> - </widget> - <widget class="QLabel" name="lbBank"> - <property name="geometry"> - <rect> - <x>10</x> - <y>30</y> - <width>81</width> - <height>20</height> - </rect> - </property> - <property name="text"> - <string>BK: 0</string> - </property> - </widget> - <widget class="QLabel" name="lbPreset"> - <property name="geometry"> - <rect> - <x>10</x> - <y>50</y> - <width>81</width> - <height>20</height> - </rect> - </property> - <property name="text"> - <string>PC: 0</string> - </property> - </widget> - <widget class="QGroupBox" name="gFilters"> - <property name="geometry"> - <rect> - <x>0</x> - <y>70</y> - <width>141</width> - <height>101</height> - </rect> - </property> - <property name="title"> - <string>Filters</string> - </property> - <widget class="QLabel" name="lbReso"> - <property name="geometry"> - <rect> - <x>70</x> - <y>80</y> - <width>66</width> - <height>20</height> - </rect> - </property> - <property name="text"> - <string>Res. 64</string> - </property> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> - </widget> - <widget class="QDial" name="dReso"> - <property name="geometry"> - <rect> - <x>80</x> - <y>30</y> - <width>50</width> - <height>51</height> - </rect> - </property> - <property name="maximum"> - <number>127</number> - </property> - <property name="value"> - <number>64</number> - </property> - <property name="notchesVisible"> - <bool>true</bool> - </property> - </widget> - <widget class="QDial" name="dCut"> - <property name="geometry"> - <rect> - <x>10</x> - <y>30</y> - <width>50</width> - <height>51</height> - </rect> - </property> - <property name="maximum"> - <number>127</number> - </property> - <property name="value"> - <number>64</number> - </property> - <property name="notchesVisible"> - <bool>true</bool> - </property> - </widget> - <widget class="QLabel" name="lbCut"> - <property name="geometry"> - <rect> - <x>0</x> - <y>80</y> - <width>71</width> - <height>20</height> - </rect> - </property> - <property name="text"> - <string>Cut. 64</string> - </property> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> - </widget> - </widget> - <widget class="QGroupBox" name="gEffects"> - <property name="geometry"> - <rect> - <x>140</x> - <y>70</y> - <width>141</width> - <height>101</height> - </rect> - </property> - <property name="title"> - <string>Effects</string> - </property> - <widget class="QLabel" name="lbChorus"> - <property name="geometry"> - <rect> - <x>70</x> - <y>80</y> - <width>66</width> - <height>20</height> - </rect> - </property> - <property name="text"> - <string>Chr. 64</string> - </property> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> - </widget> - <widget class="QDial" name="dChorus"> - <property name="geometry"> - <rect> - <x>80</x> - <y>30</y> - <width>50</width> - <height>51</height> - </rect> - </property> - <property name="maximum"> - <number>127</number> - </property> - <property name="value"> - <number>64</number> - </property> - <property name="notchesVisible"> - <bool>true</bool> - </property> - </widget> - <widget class="QDial" name="dReverb"> - <property name="geometry"> - <rect> - <x>10</x> - <y>30</y> - <width>50</width> - <height>51</height> - </rect> - </property> - <property name="maximum"> - <number>127</number> - </property> - <property name="value"> - <number>64</number> - </property> - <property name="notchesVisible"> - <bool>true</bool> - </property> - </widget> - <widget class="QLabel" name="lbReverb"> - <property name="geometry"> - <rect> - <x>0</x> - <y>80</y> - <width>71</width> - <height>20</height> - </rect> - </property> - <property name="text"> - <string>Rev. 64</string> - </property> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> - </widget> - </widget> - <widget class="QGroupBox" name="gEnvelope"> - <property name="geometry"> - <rect> - <x>0</x> - <y>170</y> - <width>211</width> - <height>101</height> - </rect> - </property> - <property name="title"> - <string>Envelope</string> - </property> - <widget class="QLabel" name="lbDecay"> - <property name="geometry"> - <rect> - <x>70</x> - <y>80</y> - <width>66</width> - <height>20</height> - </rect> - </property> - <property name="text"> - <string>Dec. 64</string> - </property> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> - </widget> - <widget class="QDial" name="dDecay"> - <property name="geometry"> - <rect> - <x>80</x> - <y>30</y> - <width>50</width> - <height>51</height> - </rect> - </property> - <property name="maximum"> - <number>127</number> - </property> - <property name="value"> - <number>64</number> - </property> - <property name="notchesVisible"> - <bool>true</bool> - </property> - </widget> - <widget class="QDial" name="dAttack"> - <property name="geometry"> - <rect> - <x>10</x> - <y>30</y> - <width>50</width> - <height>51</height> - </rect> - </property> - <property name="maximum"> - <number>127</number> - </property> - <property name="value"> - <number>64</number> - </property> - <property name="notchesVisible"> - <bool>true</bool> - </property> - </widget> - <widget class="QLabel" name="lbAttack"> - <property name="geometry"> - <rect> - <x>0</x> - <y>80</y> - <width>71</width> - <height>20</height> - </rect> - </property> - <property name="text"> - <string>Atk. 64</string> - </property> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> - </widget> - <widget class="QDial" name="dRelease"> - <property name="geometry"> - <rect> - <x>150</x> - <y>30</y> - <width>50</width> - <height>51</height> - </rect> - </property> - <property name="maximum"> - <number>127</number> - </property> - <property name="value"> - <number>64</number> - </property> - <property name="notchesVisible"> - <bool>true</bool> - </property> - </widget> - <widget class="QLabel" name="lbRelease"> - <property name="geometry"> - <rect> - <x>140</x> - <y>80</y> - <width>66</width> - <height>20</height> - </rect> - </property> - <property name="text"> - <string>Rel. 64</string> - </property> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> - </widget> - </widget> - <widget class="QGroupBox" name="gVibrato"> - <property name="geometry"> - <rect> - <x>210</x> - <y>170</y> - <width>211</width> - <height>101</height> - </rect> - </property> - <property name="title"> - <string>Vibrato</string> - </property> - <widget class="QLabel" name="lbDepth"> - <property name="geometry"> - <rect> - <x>70</x> - <y>80</y> - <width>66</width> - <height>20</height> - </rect> - </property> - <property name="text"> - <string>Dep. 64</string> - </property> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> - </widget> - <widget class="QDial" name="dDepth"> - <property name="geometry"> - <rect> - <x>80</x> - <y>30</y> - <width>50</width> - <height>51</height> - </rect> - </property> - <property name="maximum"> - <number>127</number> - </property> - <property name="value"> - <number>64</number> - </property> - <property name="notchesVisible"> - <bool>true</bool> - </property> - </widget> - <widget class="QDial" name="dRate"> - <property name="geometry"> - <rect> - <x>10</x> - <y>30</y> - <width>50</width> - <height>51</height> - </rect> - </property> - <property name="maximum"> - <number>127</number> - </property> - <property name="value"> - <number>64</number> - </property> - <property name="notchesVisible"> - <bool>true</bool> - </property> - </widget> - <widget class="QLabel" name="lbRate"> - <property name="geometry"> - <rect> - <x>0</x> - <y>80</y> - <width>71</width> - <height>20</height> - </rect> - </property> - <property name="text"> - <string>Rate 64</string> - </property> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> - </widget> - <widget class="QDial" name="dDelay"> - <property name="geometry"> - <rect> - <x>150</x> - <y>30</y> - <width>50</width> - <height>51</height> - </rect> - </property> - <property name="maximum"> - <number>127</number> - </property> - <property name="value"> - <number>64</number> - </property> - <property name="notchesVisible"> - <bool>true</bool> - </property> - </widget> - <widget class="QLabel" name="lbDelay"> - <property name="geometry"> - <rect> - <x>140</x> - <y>80</y> - <width>66</width> - <height>20</height> - </rect> - </property> - <property name="text"> - <string>Del. 64</string> - </property> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> - </widget> - </widget> - <widget class="QGroupBox" name="gMixer"> - <property name="geometry"> - <rect> - <x>280</x> - <y>70</y> - <width>141</width> - <height>101</height> - </rect> - </property> - <property name="title"> - <string>Mixer</string> - </property> - <widget class="QLabel" name="lbPan"> - <property name="geometry"> - <rect> - <x>70</x> - <y>80</y> - <width>66</width> - <height>20</height> - </rect> - </property> - <property name="text"> - <string>Pan. C</string> - </property> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> - </widget> - <widget class="QDial" name="dPan"> - <property name="geometry"> - <rect> - <x>80</x> - <y>30</y> - <width>50</width> - <height>51</height> - </rect> - </property> - <property name="maximum"> - <number>127</number> - </property> - <property name="value"> - <number>64</number> - </property> - <property name="notchesVisible"> - <bool>true</bool> - </property> - </widget> - <widget class="QLabel" name="lbVol"> - <property name="geometry"> - <rect> - <x>0</x> - <y>80</y> - <width>66</width> - <height>20</height> - </rect> - </property> - <property name="text"> - <string>Vol. 127</string> - </property> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> - </widget> - <widget class="QDial" name="dVol"> - <property name="geometry"> - <rect> - <x>10</x> - <y>30</y> - <width>50</width> - <height>51</height> - </rect> - </property> - <property name="maximum"> - <number>127</number> - </property> - <property name="value"> - <number>127</number> - </property> - <property name="notchesVisible"> - <bool>true</bool> - </property> - </widget> - </widget> - </widget> - <resources/> - <connections/> -</ui> diff --git a/qmidiplayer.src.d/qmpchannelswindow.cpp b/qmidiplayer.src.d/qmpchannelswindow.cpp deleted file mode 100644 index a9cf60e..0000000 --- a/qmidiplayer.src.d/qmpchannelswindow.cpp +++ /dev/null @@ -1,132 +0,0 @@ -#include <QCheckBox> -#include <QPushButton> -#include <QComboBox> -#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 deleted file mode 100644 index f0591b6..0000000 --- a/qmidiplayer.src.d/qmpchannelswindow.hpp +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef QMPCHANNELSWINDOW_H -#define QMPCHANNELSWINDOW_H - -#include <QLabel> -#include <QPushButton> -#include <QDialog> -#include <QShowEvent> -#include <QCloseEvent> -#include <QMoveEvent> -#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 deleted file mode 100644 index a8b43cb..0000000 --- a/qmidiplayer.src.d/qmpchannelswindow.ui +++ /dev/null @@ -1,146 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>qmpChannelsWindow</class> - <widget class="QDialog" name="qmpChannelsWindow"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>580</width> - <height>410</height> - </rect> - </property> - <property name="minimumSize"> - <size> - <width>580</width> - <height>410</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>580</width> - <height>16777215</height> - </size> - </property> - <property name="windowTitle"> - <string>Channels</string> - </property> - <layout class="QVBoxLayout" name="verticalLayout_4"> - <item> - <layout class="QVBoxLayout" name="verticalLayout_1"> - <item> - <widget class="QTableWidget" name="twChannels"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="alternatingRowColors"> - <bool>true</bool> - </property> - <property name="selectionMode"> - <enum>QAbstractItemView::NoSelection</enum> - </property> - <property name="cornerButtonEnabled"> - <bool>false</bool> - </property> - <property name="rowCount"> - <number>16</number> - </property> - <property name="columnCount"> - <number>5</number> - </property> - <row/> - <row/> - <row/> - <row/> - <row/> - <row/> - <row/> - <row/> - <row/> - <row/> - <row/> - <row/> - <row/> - <row/> - <row/> - <row/> - <column> - <property name="text"> - <string>M</string> - </property> - </column> - <column> - <property name="text"> - <string>S</string> - </property> - </column> - <column> - <property name="text"> - <string>Device</string> - </property> - </column> - <column> - <property name="text"> - <string>Preset</string> - </property> - </column> - <column> - <property name="text"> - <string>...</string> - </property> - </column> - <item row="0" column="0"> - <property name="text"> - <string/> - </property> - </item> - </widget> - </item> - </layout> - </item> - <item> - <layout class="QHBoxLayout" name="horizontalLayout"> - <item> - <widget class="QPushButton" name="pbSave"> - <property name="text"> - <string>Save</string> - </property> - <property name="iconSize"> - <size> - <width>16</width> - <height>16</height> - </size> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="pbLoad"> - <property name="text"> - <string>Load</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="pbUnmute"> - <property name="text"> - <string>Unmute All</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="pbUnsolo"> - <property name="text"> - <string>Unsolo All</string> - </property> - </widget> - </item> - </layout> - </item> - </layout> - </widget> - <resources/> - <connections/> -</ui> diff --git a/qmidiplayer.src.d/qmpefxwindow.cpp b/qmidiplayer.src.d/qmpefxwindow.cpp deleted file mode 100644 index 7d9c08e..0000000 --- a/qmidiplayer.src.d/qmpefxwindow.cpp +++ /dev/null @@ -1,198 +0,0 @@ -#include <cmath> -#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<QDial*> dials=findChildren<QDial*>(); - for(int i=0;i<dials.count();++i) - dials.at(i)->setStyle(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 deleted file mode 100644 index 2a080f0..0000000 --- a/qmidiplayer.src.d/qmpefxwindow.hpp +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef QMPEFXWINDOW_HPP -#define QMPEFXWINDOW_HPP - -#include <QDialog> -#include <QCloseEvent> -#include <QShowEvent> -#include <QMoveEvent> - -#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 deleted file mode 100644 index 4a1e0c6..0000000 --- a/qmidiplayer.src.d/qmpefxwindow.ui +++ /dev/null @@ -1,478 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>qmpEfxWindow</class> - <widget class="QDialog" name="qmpEfxWindow"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>546</width> - <height>177</height> - </rect> - </property> - <property name="minimumSize"> - <size> - <width>546</width> - <height>177</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>546</width> - <height>177</height> - </size> - </property> - <property name="windowTitle"> - <string>Effects</string> - </property> - <layout class="QHBoxLayout" name="horizontalLayout"> - <item> - <widget class="QGroupBox" name="gReverb"> - <property name="title"> - <string>Reverb</string> - </property> - <widget class="QCheckBox" name="cbEnabledR"> - <property name="geometry"> - <rect> - <x>80</x> - <y>4</y> - <width>21</width> - <height>24</height> - </rect> - </property> - <property name="text"> - <string/> - </property> - </widget> - <widget class="QDial" name="dRoom"> - <property name="geometry"> - <rect> - <x>10</x> - <y>30</y> - <width>50</width> - <height>51</height> - </rect> - </property> - <property name="maximum"> - <number>120</number> - </property> - <property name="notchesVisible"> - <bool>true</bool> - </property> - </widget> - <widget class="QDial" name="dDamp"> - <property name="geometry"> - <rect> - <x>200</x> - <y>30</y> - <width>50</width> - <height>51</height> - </rect> - </property> - <property name="maximum"> - <number>100</number> - </property> - <property name="notchesVisible"> - <bool>true</bool> - </property> - </widget> - <widget class="QDial" name="dWidth"> - <property name="geometry"> - <rect> - <x>10</x> - <y>103</y> - <width>50</width> - <height>51</height> - </rect> - </property> - <property name="maximum"> - <number>100</number> - </property> - <property name="notchesVisible"> - <bool>true</bool> - </property> - </widget> - <widget class="QDial" name="dLevelR"> - <property name="geometry"> - <rect> - <x>200</x> - <y>103</y> - <width>50</width> - <height>51</height> - </rect> - </property> - <property name="maximum"> - <number>100</number> - </property> - <property name="notchesVisible"> - <bool>true</bool> - </property> - </widget> - <widget class="QLabel" name="lbRoom"> - <property name="geometry"> - <rect> - <x>60</x> - <y>30</y> - <width>41</width> - <height>20</height> - </rect> - </property> - <property name="text"> - <string>Room</string> - </property> - </widget> - <widget class="QSpinBox" name="sbRoom"> - <property name="geometry"> - <rect> - <x>60</x> - <y>50</y> - <width>51</width> - <height>21</height> - </rect> - </property> - <property name="maximum"> - <number>120</number> - </property> - </widget> - <widget class="QLabel" name="lbDamp"> - <property name="geometry"> - <rect> - <x>140</x> - <y>30</y> - <width>51</width> - <height>20</height> - </rect> - </property> - <property name="text"> - <string>Damp</string> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - </widget> - <widget class="QSpinBox" name="sbDamp"> - <property name="geometry"> - <rect> - <x>140</x> - <y>50</y> - <width>56</width> - <height>21</height> - </rect> - </property> - <property name="maximum"> - <number>100</number> - </property> - </widget> - <widget class="QLabel" name="lbWidth"> - <property name="geometry"> - <rect> - <x>60</x> - <y>100</y> - <width>51</width> - <height>20</height> - </rect> - </property> - <property name="text"> - <string>Width</string> - </property> - </widget> - <widget class="QSpinBox" name="sbWidth"> - <property name="geometry"> - <rect> - <x>60</x> - <y>120</y> - <width>56</width> - <height>21</height> - </rect> - </property> - <property name="maximum"> - <number>100</number> - </property> - </widget> - <widget class="QLabel" name="lbLevelR"> - <property name="geometry"> - <rect> - <x>145</x> - <y>100</y> - <width>51</width> - <height>20</height> - </rect> - </property> - <property name="text"> - <string>Level</string> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - </widget> - <widget class="QSpinBox" name="sbLevelR"> - <property name="geometry"> - <rect> - <x>140</x> - <y>120</y> - <width>56</width> - <height>21</height> - </rect> - </property> - <property name="maximum"> - <number>100</number> - </property> - </widget> - </widget> - </item> - <item> - <widget class="QGroupBox" name="gChorus"> - <property name="title"> - <string>Chorus</string> - </property> - <widget class="QCheckBox" name="cbEnabledC"> - <property name="geometry"> - <rect> - <x>80</x> - <y>4</y> - <width>21</width> - <height>24</height> - </rect> - </property> - <property name="text"> - <string/> - </property> - </widget> - <widget class="QDial" name="dFeedBack"> - <property name="geometry"> - <rect> - <x>10</x> - <y>30</y> - <width>50</width> - <height>51</height> - </rect> - </property> - <property name="maximum"> - <number>99</number> - </property> - <property name="notchesVisible"> - <bool>true</bool> - </property> - </widget> - <widget class="QDial" name="dRate"> - <property name="geometry"> - <rect> - <x>200</x> - <y>30</y> - <width>50</width> - <height>51</height> - </rect> - </property> - <property name="minimum"> - <number>29</number> - </property> - <property name="maximum"> - <number>500</number> - </property> - <property name="value"> - <number>29</number> - </property> - <property name="notchesVisible"> - <bool>true</bool> - </property> - </widget> - <widget class="QDial" name="dDepth"> - <property name="geometry"> - <rect> - <x>10</x> - <y>103</y> - <width>50</width> - <height>51</height> - </rect> - </property> - <property name="maximum"> - <number>210</number> - </property> - <property name="notchesVisible"> - <bool>true</bool> - </property> - </widget> - <widget class="QDial" name="dLevelC"> - <property name="geometry"> - <rect> - <x>200</x> - <y>103</y> - <width>50</width> - <height>51</height> - </rect> - </property> - <property name="maximum"> - <number>100</number> - </property> - <property name="notchesVisible"> - <bool>true</bool> - </property> - </widget> - <widget class="QLabel" name="lbFeedBack"> - <property name="geometry"> - <rect> - <x>60</x> - <y>30</y> - <width>71</width> - <height>20</height> - </rect> - </property> - <property name="text"> - <string>Feedback</string> - </property> - </widget> - <widget class="QSpinBox" name="sbFeedBack"> - <property name="geometry"> - <rect> - <x>60</x> - <y>50</y> - <width>51</width> - <height>21</height> - </rect> - </property> - <property name="maximum"> - <number>99</number> - </property> - </widget> - <widget class="QLabel" name="lbRate"> - <property name="geometry"> - <rect> - <x>140</x> - <y>30</y> - <width>51</width> - <height>20</height> - </rect> - </property> - <property name="text"> - <string>Rate</string> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - </widget> - <widget class="QLabel" name="lbDepth"> - <property name="geometry"> - <rect> - <x>60</x> - <y>100</y> - <width>51</width> - <height>20</height> - </rect> - </property> - <property name="text"> - <string>Depth</string> - </property> - </widget> - <widget class="QLabel" name="lbLevelC"> - <property name="geometry"> - <rect> - <x>145</x> - <y>100</y> - <width>51</width> - <height>20</height> - </rect> - </property> - <property name="text"> - <string>Level</string> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - </widget> - <widget class="QSpinBox" name="sbLevelC"> - <property name="geometry"> - <rect> - <x>140</x> - <y>120</y> - <width>56</width> - <height>21</height> - </rect> - </property> - <property name="maximum"> - <number>100</number> - </property> - </widget> - <widget class="QDoubleSpinBox" name="sbRate"> - <property name="geometry"> - <rect> - <x>137</x> - <y>50</y> - <width>61</width> - <height>21</height> - </rect> - </property> - <property name="minimum"> - <double>0.290000000000000</double> - </property> - <property name="maximum"> - <double>5.000000000000000</double> - </property> - <property name="singleStep"> - <double>0.100000000000000</double> - </property> - </widget> - <widget class="QLabel" name="lbLFO"> - <property name="geometry"> - <rect> - <x>35</x> - <y>77</y> - <width>41</width> - <height>20</height> - </rect> - </property> - <property name="text"> - <string>LFO</string> - </property> - </widget> - <widget class="QRadioButton" name="rbSine"> - <property name="geometry"> - <rect> - <x>70</x> - <y>77</y> - <width>61</width> - <height>20</height> - </rect> - </property> - <property name="text"> - <string>Sine</string> - </property> - </widget> - <widget class="QRadioButton" name="rbTriangle"> - <property name="geometry"> - <rect> - <x>145</x> - <y>77</y> - <width>91</width> - <height>20</height> - </rect> - </property> - <property name="text"> - <string>Trian&gle</string> - </property> - </widget> - <widget class="QDoubleSpinBox" name="sbDepth"> - <property name="geometry"> - <rect> - <x>60</x> - <y>120</y> - <width>51</width> - <height>21</height> - </rect> - </property> - <property name="decimals"> - <number>1</number> - </property> - <property name="maximum"> - <double>21.000000000000000</double> - </property> - <property name="singleStep"> - <double>0.100000000000000</double> - </property> - </widget> - </widget> - </item> - </layout> - </widget> - <resources/> - <connections/> -</ui> diff --git a/qmidiplayer.src.d/qmphelpwindow.cpp b/qmidiplayer.src.d/qmphelpwindow.cpp deleted file mode 100644 index 10cf083..0000000 --- a/qmidiplayer.src.d/qmphelpwindow.cpp +++ /dev/null @@ -1,31 +0,0 @@ -#include <fluidsynth.h> -#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 deleted file mode 100644 index c2052b2..0000000 --- a/qmidiplayer.src.d/qmphelpwindow.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef QMPHELPWINDOW_H -#define QMPHELPWINDOW_H - -#include <QDialog> -#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 deleted file mode 100644 index fd21b5f..0000000 --- a/qmidiplayer.src.d/qmphelpwindow.ui +++ /dev/null @@ -1,34 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>qmpHelpWindow</class> - <widget class="QDialog" name="qmpHelpWindow"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>640</width> - <height>360</height> - </rect> - </property> - <property name="minimumSize"> - <size> - <width>640</width> - <height>360</height> - </size> - </property> - <property name="windowTitle"> - <string>Help</string> - </property> - <layout class="QVBoxLayout" name="verticalLayout"> - <item> - <widget class="QTextBrowser" name="textBrowser"> - <property name="openExternalLinks"> - <bool>true</bool> - </property> - </widget> - </item> - </layout> - </widget> - <resources/> - <connections/> -</ui> diff --git a/qmidiplayer.src.d/qmpimidimapper.hpp b/qmidiplayer.src.d/qmpimidimapper.hpp deleted file mode 100644 index d35dbb9..0000000 --- a/qmidiplayer.src.d/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/qmidiplayer.src.d/qmpinfowindow.cpp b/qmidiplayer.src.d/qmpinfowindow.cpp deleted file mode 100644 index 689a756..0000000 --- a/qmidiplayer.src.d/qmpinfowindow.cpp +++ /dev/null @@ -1,57 +0,0 @@ -#include <QTextCodec> -#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 deleted file mode 100644 index 9a1e389..0000000 --- a/qmidiplayer.src.d/qmpinfowindow.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef QMPINFOWINDOW_HPP -#define QMPINFOWINDOW_HPP - -#include <QDialog> - -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 deleted file mode 100644 index 664531a..0000000 --- a/qmidiplayer.src.d/qmpinfowindow.ui +++ /dev/null @@ -1,91 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>qmpInfoWindow</class> - <widget class="QDialog" name="qmpInfoWindow"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>400</width> - <height>142</height> - </rect> - </property> - <property name="minimumSize"> - <size> - <width>400</width> - <height>142</height> - </size> - </property> - <property name="windowTitle"> - <string>File Information</string> - </property> - <layout class="QVBoxLayout" name="verticalLayout"> - <item> - <widget class="QLabel" name="lbFileName"> - <property name="text"> - <string>File name: </string> - </property> - </widget> - </item> - <item> - <layout class="QHBoxLayout" name="horizontalLayout"> - <item> - <widget class="QLabel" name="lbTempo"> - <property name="text"> - <string>Tempo: </string> - </property> - </widget> - </item> - <item> - <widget class="QLabel" name="lbKeySig"> - <property name="text"> - <string>Key Sig.: </string> - </property> - </widget> - </item> - <item> - <widget class="QLabel" name="lbTimeSig"> - <property name="text"> - <string>Time Sig.:</string> - </property> - </widget> - </item> - </layout> - </item> - <item> - <widget class="QLabel" name="lbTitle"> - <property name="text"> - <string>Title: </string> - </property> - </widget> - </item> - <item> - <widget class="QLabel" name="lbCopyright"> - <property name="text"> - <string>Copyright: </string> - </property> - </widget> - </item> - <item> - <layout class="QHBoxLayout" name="horizontalLayout_2"> - <item> - <widget class="QLabel" name="lbNoteCount"> - <property name="text"> - <string>Note count: </string> - </property> - </widget> - </item> - <item> - <widget class="QLabel" name="lbFileStandard"> - <property name="text"> - <string>File standard: </string> - </property> - </widget> - </item> - </layout> - </item> - </layout> - </widget> - <resources/> - <connections/> -</ui> diff --git a/qmidiplayer.src.d/qmpmainwindow.cpp b/qmidiplayer.src.d/qmpmainwindow.cpp deleted file mode 100644 index 453bd01..0000000 --- a/qmidiplayer.src.d/qmpmainwindow.cpp +++ /dev/null @@ -1,510 +0,0 @@ -#include <cstdio> -#include <QUrl> -#include <QMimeData> -#include <QDirIterator> -#include <QDesktopWidget> -#include "qmpmainwindow.hpp" -#include "ui_qmpmainwindow.h" -#include "../common/qmpmidiplay.hpp" -#ifdef _WIN32 -#include <Windows.h> -#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;i<argc;++i) - { - if(argv[i][0]=='-') - { - if(!strcmp(argv[i],"--help")) - { - printf("Usage: %s [Options] [Midi Files]\n",argv[0]); - printf("Possible options are: \n"); - printf("-l, --load-all-files Load all files from the same folder.\n"); - printf("--help Show this help and exit.\n"); - printf("--version Show this version information and exit.\n"); - return 1; - } - if(!strcmp(argv[i],"--version")) - { - printf("QMidiPlayer %s\n",APP_VERSION); - return 1; - } - if(!strcmp(argv[i],"-l")||!strcmp(argv[i],"--load-all-files")) - loadfolder=true; - } - else - if(fluid_is_midifile(argv[i])) - { - if(!havemidi){havemidi=true;plistw->emptyList();} - 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<QUrl> l=event->mimeData()->urls(); - QStringList sl; - for(int i=0;i<l.size();++i) - sl.push_back(l.at(i).toLocalFile()); - plistw->insertItems(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<double> elapsed= - std::chrono::duration_cast<std::chrono::duration<double>>(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 deleted file mode 100644 index 517f792..0000000 --- a/qmidiplayer.src.d/qmpmainwindow.hpp +++ /dev/null @@ -1,90 +0,0 @@ -#ifndef QMPMAINWINDOW_H -#define QMPMAINWINDOW_H - -#include <QMainWindow> -#include <QTimer> -#include <QCloseEvent> -#include <QMoveEvent> -#include <QDropEvent> -#include <QDragEnterEvent> -#include <QAction> -#include <QMenu> -#include <thread> -#include <chrono> -#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 deleted file mode 100644 index 0764e09..0000000 --- a/qmidiplayer.src.d/qmpmainwindow.ui +++ /dev/null @@ -1,413 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>qmpMainWindow</class> - <widget class="QMainWindow" name="qmpMainWindow"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>435</width> - <height>245</height> - </rect> - </property> - <property name="minimumSize"> - <size> - <width>435</width> - <height>245</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>435</width> - <height>245</height> - </size> - </property> - <property name="acceptDrops"> - <bool>true</bool> - </property> - <property name="windowTitle"> - <string>QMidiPlayer</string> - </property> - <property name="windowIcon"> - <iconset resource="resources.qrc"> - <normaloff>:/img/qmidiplyr.png</normaloff>:/img/qmidiplyr.png</iconset> - </property> - <widget class="QWidget" name="centralWidget"> - <widget class="QLabel" name="lbFileName"> - <property name="geometry"> - <rect> - <x>30</x> - <y>20</y> - <width>311</width> - <height>41</height> - </rect> - </property> - <property name="font"> - <font> - <pointsize>18</pointsize> - </font> - </property> - <property name="contextMenuPolicy"> - <enum>Qt::CustomContextMenu</enum> - </property> - <property name="text"> - <string>somefile.mid</string> - </property> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> - </widget> - <widget class="QSlider" name="hsTimer"> - <property name="geometry"> - <rect> - <x>20</x> - <y>90</y> - <width>321</width> - <height>20</height> - </rect> - </property> - <property name="maximum"> - <number>100</number> - </property> - <property name="pageStep"> - <number>0</number> - </property> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - </widget> - <widget class="QPushButton" name="pbPlayPause"> - <property name="geometry"> - <rect> - <x>20</x> - <y>110</y> - <width>61</width> - <height>36</height> - </rect> - </property> - <property name="text"> - <string/> - </property> - <property name="icon"> - <iconset resource="resources.qrc"> - <normaloff>:/img/play.png</normaloff>:/img/play.png</iconset> - </property> - <property name="iconSize"> - <size> - <width>32</width> - <height>32</height> - </size> - </property> - </widget> - <widget class="QPushButton" name="pbStop"> - <property name="geometry"> - <rect> - <x>80</x> - <y>110</y> - <width>61</width> - <height>36</height> - </rect> - </property> - <property name="text"> - <string/> - </property> - <property name="icon"> - <iconset resource="resources.qrc"> - <normaloff>:/img/stop.png</normaloff>:/img/stop.png</iconset> - </property> - <property name="iconSize"> - <size> - <width>32</width> - <height>32</height> - </size> - </property> - </widget> - <widget class="QPushButton" name="pbPrev"> - <property name="geometry"> - <rect> - <x>140</x> - <y>110</y> - <width>61</width> - <height>36</height> - </rect> - </property> - <property name="text"> - <string/> - </property> - <property name="icon"> - <iconset resource="resources.qrc"> - <normaloff>:/img/prev.png</normaloff>:/img/prev.png</iconset> - </property> - <property name="iconSize"> - <size> - <width>32</width> - <height>32</height> - </size> - </property> - </widget> - <widget class="QPushButton" name="pbNext"> - <property name="geometry"> - <rect> - <x>200</x> - <y>110</y> - <width>61</width> - <height>36</height> - </rect> - </property> - <property name="text"> - <string/> - </property> - <property name="icon"> - <iconset resource="resources.qrc"> - <normaloff>:/img/next.png</normaloff>:/img/next.png</iconset> - </property> - <property name="iconSize"> - <size> - <width>32</width> - <height>32</height> - </size> - </property> - </widget> - <widget class="QPushButton" name="pbSettings"> - <property name="geometry"> - <rect> - <x>280</x> - <y>110</y> - <width>61</width> - <height>36</height> - </rect> - </property> - <property name="text"> - <string/> - </property> - <property name="icon"> - <iconset resource="resources.qrc"> - <normaloff>:/img/settings.png</normaloff>:/img/settings.png</iconset> - </property> - <property name="iconSize"> - <size> - <width>32</width> - <height>32</height> - </size> - </property> - <property name="checkable"> - <bool>true</bool> - </property> - </widget> - <widget class="QPushButton" name="pbChannels"> - <property name="geometry"> - <rect> - <x>20</x> - <y>160</y> - <width>151</width> - <height>36</height> - </rect> - </property> - <property name="styleSheet"> - <string notr="true">text-align:left</string> - </property> - <property name="text"> - <string>Channels</string> - </property> - <property name="icon"> - <iconset resource="resources.qrc"> - <normaloff>:/img/channel.png</normaloff>:/img/channel.png</iconset> - </property> - <property name="iconSize"> - <size> - <width>32</width> - <height>32</height> - </size> - </property> - <property name="checkable"> - <bool>true</bool> - </property> - </widget> - <widget class="QPushButton" name="pbPList"> - <property name="geometry"> - <rect> - <x>190</x> - <y>160</y> - <width>151</width> - <height>36</height> - </rect> - </property> - <property name="styleSheet"> - <string notr="true">text-align:left</string> - </property> - <property name="text"> - <string>Playlist</string> - </property> - <property name="icon"> - <iconset resource="resources.qrc"> - <normaloff>:/img/list.png</normaloff>:/img/list.png</iconset> - </property> - <property name="iconSize"> - <size> - <width>32</width> - <height>32</height> - </size> - </property> - <property name="checkable"> - <bool>true</bool> - </property> - <property name="checked"> - <bool>false</bool> - </property> - <property name="flat"> - <bool>false</bool> - </property> - </widget> - <widget class="QPushButton" name="pbEfx"> - <property name="geometry"> - <rect> - <x>20</x> - <y>200</y> - <width>151</width> - <height>36</height> - </rect> - </property> - <property name="styleSheet"> - <string notr="true">text-align:left</string> - </property> - <property name="text"> - <string>Effects</string> - </property> - <property name="icon"> - <iconset resource="resources.qrc"> - <normaloff>:/img/effects.png</normaloff>:/img/effects.png</iconset> - </property> - <property name="iconSize"> - <size> - <width>32</width> - <height>32</height> - </size> - </property> - <property name="checkable"> - <bool>true</bool> - </property> - </widget> - <widget class="QPushButton" name="pbVisualization"> - <property name="geometry"> - <rect> - <x>190</x> - <y>200</y> - <width>151</width> - <height>36</height> - </rect> - </property> - <property name="styleSheet"> - <string notr="true">text-align:left</string> - </property> - <property name="text"> - <string>Visualization</string> - </property> - <property name="icon"> - <iconset resource="resources.qrc"> - <normaloff>:/img/visualization.png</normaloff>:/img/visualization.png</iconset> - </property> - <property name="iconSize"> - <size> - <width>32</width> - <height>32</height> - </size> - </property> - </widget> - <widget class="QLabel" name="lbPolyphone"> - <property name="geometry"> - <rect> - <x>320</x> - <y>20</y> - <width>111</width> - <height>20</height> - </rect> - </property> - <property name="text"> - <string><html><head/><body><p>Poly: 0/0</p></body></html></string> - </property> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> - </widget> - <widget class="QSlider" name="vsMasterVol"> - <property name="geometry"> - <rect> - <x>370</x> - <y>50</y> - <width>20</width> - <height>160</height> - </rect> - </property> - <property name="maximum"> - <number>100</number> - </property> - <property name="value"> - <number>50</number> - </property> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - </widget> - <widget class="QLabel" name="lbMasterVol"> - <property name="geometry"> - <rect> - <x>360</x> - <y>210</y> - <width>61</width> - <height>20</height> - </rect> - </property> - <property name="text"> - <string>Master</string> - </property> - </widget> - <widget class="QLabel" name="lbCurTime"> - <property name="geometry"> - <rect> - <x>20</x> - <y>70</y> - <width>66</width> - <height>20</height> - </rect> - </property> - <property name="text"> - <string>00:00</string> - </property> - </widget> - <widget class="QLabel" name="lbFinTime"> - <property name="geometry"> - <rect> - <x>270</x> - <y>70</y> - <width>66</width> - <height>20</height> - </rect> - </property> - <property name="text"> - <string>00:00</string> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - </widget> - <widget class="QPushButton" name="pushButton"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>21</width> - <height>21</height> - </rect> - </property> - <property name="text"> - <string>?</string> - </property> - </widget> - </widget> - </widget> - <layoutdefault spacing="6" margin="11"/> - <resources> - <include location="resources.qrc"/> - </resources> - <connections/> -</ui> diff --git a/qmidiplayer.src.d/qmpplistwindow.cpp b/qmidiplayer.src.d/qmpplistwindow.cpp deleted file mode 100644 index 8f04fc1..0000000 --- a/qmidiplayer.src.d/qmpplistwindow.cpp +++ /dev/null @@ -1,308 +0,0 @@ -#include <cstdlib> -#include <ctime> -#include <QFileDialog> -#include <QDir> -#include <QDirIterator> -#include <QSettings> -#include <QUrl> -#include <QMimeData> -#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;i<ui->lwFiles->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<QUrl> l=event->mimeData()->urls(); - QStringList sl; - for(int i=0;i<l.size();++i) - sl.push_back(l.at(i).toLocalFile()); - insertItems(sl); -} -void qmpPlistWindow::dragEnterEvent(QDragEnterEvent *event) -{ - //if(event->mimeData()->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;i<sl.size();++i) - { - ui->lwFiles->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<QListWidgetItem*> sl=ui->lwFiles->selectedItems(); - for(int i=0;i<sl.size();++i) - { - ui->lwFiles->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;i<ui->lwFiles->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 deleted file mode 100644 index 6ceeb60..0000000 --- a/qmidiplayer.src.d/qmpplistwindow.hpp +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef QMPPLISTWINDOW_H -#define QMPPLISTWINDOW_H - -#include <QDialog> -#include <QShowEvent> -#include <QCloseEvent> -#include <QMoveEvent> -#include <QDropEvent> -#include <QDragEnterEvent> -#include <QListWidgetItem> - -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 deleted file mode 100644 index 99124df..0000000 --- a/qmidiplayer.src.d/qmpplistwindow.ui +++ /dev/null @@ -1,263 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>qmpPlistWindow</class> - <widget class="QDialog" name="qmpPlistWindow"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>530</width> - <height>321</height> - </rect> - </property> - <property name="minimumSize"> - <size> - <width>530</width> - <height>321</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>530</width> - <height>321</height> - </size> - </property> - <property name="acceptDrops"> - <bool>true</bool> - </property> - <property name="windowTitle"> - <string>Playlist</string> - </property> - <widget class="QPushButton" name="pbAdd"> - <property name="geometry"> - <rect> - <x>10</x> - <y>280</y> - <width>121</width> - <height>36</height> - </rect> - </property> - <property name="styleSheet"> - <string notr="true">text-align:left</string> - </property> - <property name="text"> - <string>Add</string> - </property> - <property name="icon"> - <iconset resource="resources.qrc"> - <normaloff>:/img/add.png</normaloff>:/img/add.png</iconset> - </property> - <property name="iconSize"> - <size> - <width>32</width> - <height>32</height> - </size> - </property> - </widget> - <widget class="QPushButton" name="pbAddFolder"> - <property name="geometry"> - <rect> - <x>140</x> - <y>280</y> - <width>121</width> - <height>36</height> - </rect> - </property> - <property name="styleSheet"> - <string notr="true">text-align:left</string> - </property> - <property name="text"> - <string>Add Folder</string> - </property> - <property name="icon"> - <iconset resource="resources.qrc"> - <normaloff>:/img/addfolder.png</normaloff>:/img/addfolder.png</iconset> - </property> - <property name="iconSize"> - <size> - <width>32</width> - <height>32</height> - </size> - </property> - </widget> - <widget class="QPushButton" name="pbRepeat"> - <property name="geometry"> - <rect> - <x>270</x> - <y>240</y> - <width>121</width> - <height>36</height> - </rect> - </property> - <property name="styleSheet"> - <string notr="true">text-align:left</string> - </property> - <property name="text"> - <string>Repeat Off</string> - </property> - <property name="icon"> - <iconset resource="resources.qrc"> - <normaloff>:/img/repeat-non.png</normaloff>:/img/repeat-non.png</iconset> - </property> - <property name="iconSize"> - <size> - <width>32</width> - <height>32</height> - </size> - </property> - </widget> - <widget class="QPushButton" name="pbShuffle"> - <property name="geometry"> - <rect> - <x>400</x> - <y>240</y> - <width>121</width> - <height>36</height> - </rect> - </property> - <property name="styleSheet"> - <string notr="true">text-align:left</string> - </property> - <property name="text"> - <string>Shuffle Off</string> - </property> - <property name="icon"> - <iconset resource="resources.qrc"> - <normaloff>:/img/shuffle-off.png</normaloff>:/img/shuffle-off.png</iconset> - </property> - <property name="iconSize"> - <size> - <width>32</width> - <height>32</height> - </size> - </property> - </widget> - <widget class="QPushButton" name="pbSave"> - <property name="geometry"> - <rect> - <x>10</x> - <y>240</y> - <width>121</width> - <height>36</height> - </rect> - </property> - <property name="styleSheet"> - <string notr="true">text-align:left</string> - </property> - <property name="text"> - <string>Save</string> - </property> - <property name="icon"> - <iconset resource="resources.qrc"> - <normaloff>:/img/save.png</normaloff>:/img/save.png</iconset> - </property> - <property name="iconSize"> - <size> - <width>32</width> - <height>32</height> - </size> - </property> - </widget> - <widget class="QPushButton" name="pbLoad"> - <property name="geometry"> - <rect> - <x>140</x> - <y>240</y> - <width>121</width> - <height>36</height> - </rect> - </property> - <property name="styleSheet"> - <string notr="true">text-align:left</string> - </property> - <property name="text"> - <string>Load</string> - </property> - <property name="icon"> - <iconset resource="resources.qrc"> - <normaloff>:/img/load.png</normaloff>:/img/load.png</iconset> - </property> - <property name="iconSize"> - <size> - <width>32</width> - <height>32</height> - </size> - </property> - </widget> - <widget class="QPushButton" name="pbRemove"> - <property name="geometry"> - <rect> - <x>270</x> - <y>280</y> - <width>121</width> - <height>36</height> - </rect> - </property> - <property name="styleSheet"> - <string notr="true">text-align:left</string> - </property> - <property name="text"> - <string>Remove</string> - </property> - <property name="icon"> - <iconset resource="resources.qrc"> - <normaloff>:/img/remove.png</normaloff>:/img/remove.png</iconset> - </property> - <property name="iconSize"> - <size> - <width>32</width> - <height>32</height> - </size> - </property> - </widget> - <widget class="QPushButton" name="pbClear"> - <property name="geometry"> - <rect> - <x>400</x> - <y>280</y> - <width>121</width> - <height>36</height> - </rect> - </property> - <property name="styleSheet"> - <string notr="true">text-align:left</string> - </property> - <property name="text"> - <string>Clear</string> - </property> - <property name="icon"> - <iconset resource="resources.qrc"> - <normaloff>:/img/clear.png</normaloff>:/img/clear.png</iconset> - </property> - <property name="iconSize"> - <size> - <width>32</width> - <height>32</height> - </size> - </property> - </widget> - <widget class="QListWidget" name="lwFiles"> - <property name="geometry"> - <rect> - <x>10</x> - <y>10</y> - <width>511</width> - <height>221</height> - </rect> - </property> - <property name="acceptDrops"> - <bool>false</bool> - </property> - <property name="dragEnabled"> - <bool>true</bool> - </property> - <property name="dragDropMode"> - <enum>QAbstractItemView::InternalMove</enum> - </property> - </widget> - </widget> - <resources> - <include location="resources.qrc"/> - </resources> - <connections/> -</ui> diff --git a/qmidiplayer.src.d/qmppresetselect.cpp b/qmidiplayer.src.d/qmppresetselect.cpp deleted file mode 100644 index be589c5..0000000 --- a/qmidiplayer.src.d/qmppresetselect.cpp +++ /dev/null @@ -1,99 +0,0 @@ -#include <cstdio> -#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;i<ui->lwBankSelect->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 deleted file mode 100644 index 54f5764..0000000 --- a/qmidiplayer.src.d/qmppresetselect.hpp +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef QMPPRESETSELECT_H -#define QMPPRESETSELECT_H - -#include <QDialog> -#include <QShowEvent> - -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 deleted file mode 100644 index f18600d..0000000 --- a/qmidiplayer.src.d/qmppresetselect.ui +++ /dev/null @@ -1,106 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>qmpPresetSelector</class> - <widget class="QDialog" name="qmpPresetSelector"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>404</width> - <height>300</height> - </rect> - </property> - <property name="minimumSize"> - <size> - <width>404</width> - <height>300</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>404</width> - <height>300</height> - </size> - </property> - <property name="windowTitle"> - <string>Preset Selection</string> - </property> - <property name="modal"> - <bool>true</bool> - </property> - <widget class="QListWidget" name="lwBankSelect"> - <property name="geometry"> - <rect> - <x>10</x> - <y>30</y> - <width>71</width> - <height>221</height> - </rect> - </property> - </widget> - <widget class="QListWidget" name="lwPresetSelect"> - <property name="geometry"> - <rect> - <x>90</x> - <y>30</y> - <width>301</width> - <height>221</height> - </rect> - </property> - </widget> - <widget class="QLabel" name="lbBnk"> - <property name="geometry"> - <rect> - <x>10</x> - <y>10</y> - <width>66</width> - <height>20</height> - </rect> - </property> - <property name="text"> - <string>Bank</string> - </property> - </widget> - <widget class="QLabel" name="lbPst"> - <property name="geometry"> - <rect> - <x>90</x> - <y>10</y> - <width>66</width> - <height>20</height> - </rect> - </property> - <property name="text"> - <string>Preset</string> - </property> - </widget> - <widget class="QPushButton" name="pbOk"> - <property name="geometry"> - <rect> - <x>300</x> - <y>260</y> - <width>97</width> - <height>36</height> - </rect> - </property> - <property name="text"> - <string>OK</string> - </property> - </widget> - <widget class="QPushButton" name="pbCancel"> - <property name="geometry"> - <rect> - <x>190</x> - <y>260</y> - <width>97</width> - <height>36</height> - </rect> - </property> - <property name="text"> - <string>Cancel</string> - </property> - </widget> - </widget> - <resources/> - <connections/> -</ui> diff --git a/qmidiplayer.src.d/qmpsettingswindow.cpp b/qmidiplayer.src.d/qmpsettingswindow.cpp deleted file mode 100644 index c2e31a2..0000000 --- a/qmidiplayer.src.d/qmpsettingswindow.cpp +++ /dev/null @@ -1,289 +0,0 @@ -#include <QFileDialog> -#include <QDir> -#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;i<ui->cbEncoding->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;i<ui->cbAudioDrv->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;i<ui->cbBufSize->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;i<ui->cbBufCnt->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;i<ui->cbFormat->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;i<ui->cbFrequency->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;i<ui->cbBSMode->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;i<ui->lwSoundfont->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;i<sl.size();++i) - { - ui->lwSoundfont->addItem(new QListWidgetItem(sl.at(i))); - } -} - -void qmpSettingsWindow::on_pbRemove_clicked() -{ - QList<QListWidgetItem*> sl=ui->lwSoundfont->selectedItems(); - for(int i=0;i<sl.size();++i) - { - ui->lwSoundfont->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 deleted file mode 100644 index c506de4..0000000 --- a/qmidiplayer.src.d/qmpsettingswindow.hpp +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef QMPSETTINGSWINDOW_H -#define QMPSETTINGSWINDOW_H - -#include <QDialog> -#include <QCloseEvent> -#include <QSettings> -#include <QListWidget> - -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 deleted file mode 100644 index 330afa2..0000000 --- a/qmidiplayer.src.d/qmpsettingswindow.ui +++ /dev/null @@ -1,761 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>qmpSettingsWindow</class> - <widget class="QDialog" name="qmpSettingsWindow"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>494</width> - <height>445</height> - </rect> - </property> - <property name="minimumSize"> - <size> - <width>494</width> - <height>445</height> - </size> - </property> - <property name="windowTitle"> - <string>Settings</string> - </property> - <layout class="QVBoxLayout" name="verticalLayout"> - <item> - <widget class="QTabWidget" name="tabWidget"> - <property name="currentIndex"> - <number>0</number> - </property> - <widget class="QWidget" name="tab"> - <attribute name="title"> - <string>Midi</string> - </attribute> - <layout class="QVBoxLayout" name="verticalLayout_4"> - <item> - <layout class="QHBoxLayout" name="horizontalLayout_6"> - <item> - <widget class="QLabel" name="lbOutputDevice"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Default Output Device</string> - </property> - </widget> - </item> - <item> - <widget class="QComboBox" name="cbOutputDevice"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <item> - <property name="text"> - <string>Internal FluidSynth</string> - </property> - </item> - </widget> - </item> - </layout> - </item> - <item> - <widget class="QCheckBox" name="cbDisableMapping"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Disable Midi Mapping</string> - </property> - </widget> - </item> - <item> - <widget class="QCheckBox" name="cbSendSysx"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Send SysEx</string> - </property> - </widget> - </item> - <item> - <widget class="QCheckBox" name="cbWaitVoice"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Wait for remaining voices before stopping</string> - </property> - </widget> - </item> - <item> - <layout class="QHBoxLayout" name="horizontalLayout_7"> - <item> - <widget class="QLabel" name="lbEncoding"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Text Encoding</string> - </property> - </widget> - </item> - <item> - <widget class="QComboBox" name="cbEncoding"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <item> - <property name="text"> - <string>Unicode</string> - </property> - </item> - <item> - <property name="text"> - <string>Big5</string> - </property> - </item> - <item> - <property name="text"> - <string>Big5-HKSCS</string> - </property> - </item> - <item> - <property name="text"> - <string>CP949</string> - </property> - </item> - <item> - <property name="text"> - <string>EUC-JP</string> - </property> - </item> - <item> - <property name="text"> - <string>EUC-KR</string> - </property> - </item> - <item> - <property name="text"> - <string>GB18030</string> - </property> - </item> - <item> - <property name="text"> - <string>KOI8-R</string> - </property> - </item> - <item> - <property name="text"> - <string>KOI8-U</string> - </property> - </item> - <item> - <property name="text"> - <string>Macintosh</string> - </property> - </item> - <item> - <property name="text"> - <string>Shift-JIS</string> - </property> - </item> - </widget> - </item> - </layout> - </item> - </layout> - </widget> - <widget class="QWidget" name="tab_2"> - <attribute name="title"> - <string>Synth</string> - </attribute> - <layout class="QGridLayout" name="gridLayout_2"> - <item row="2" column="0"> - <widget class="QLabel" name="lbBufCnt"> - <property name="text"> - <string>Audio Buffer Count</string> - </property> - </widget> - </item> - <item row="1" column="0"> - <widget class="QLabel" name="lbBufSize"> - <property name="text"> - <string>Audio Buffer Size</string> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QComboBox" name="cbBufSize"> - <property name="editable"> - <bool>true</bool> - </property> - <property name="currentIndex"> - <number>1</number> - </property> - <item> - <property name="text"> - <string>64</string> - </property> - </item> - <item> - <property name="text"> - <string>128</string> - </property> - </item> - <item> - <property name="text"> - <string>256</string> - </property> - </item> - <item> - <property name="text"> - <string>512</string> - </property> - </item> - <item> - <property name="text"> - <string>1024</string> - </property> - </item> - <item> - <property name="text"> - <string>2048</string> - </property> - </item> - <item> - <property name="text"> - <string>4096</string> - </property> - </item> - <item> - <property name="text"> - <string>8192</string> - </property> - </item> - </widget> - </item> - <item row="4" column="0"> - <widget class="QLabel" name="lbFrequency"> - <property name="text"> - <string>Audio Frequency</string> - </property> - </widget> - </item> - <item row="2" column="1"> - <widget class="QComboBox" name="cbBufCnt"> - <property name="editable"> - <bool>true</bool> - </property> - <item> - <property name="text"> - <string>2</string> - </property> - </item> - <item> - <property name="text"> - <string>4</string> - </property> - </item> - <item> - <property name="text"> - <string>8</string> - </property> - </item> - <item> - <property name="text"> - <string>16</string> - </property> - </item> - <item> - <property name="text"> - <string>32</string> - </property> - </item> - <item> - <property name="text"> - <string>64</string> - </property> - </item> - </widget> - </item> - <item row="0" column="0"> - <widget class="QLabel" name="lbAudioDrv"> - <property name="text"> - <string>Audio Driver</string> - </property> - </widget> - </item> - <item row="3" column="1"> - <widget class="QComboBox" name="cbFormat"> - <item> - <property name="text"> - <string>16bits</string> - </property> - </item> - <item> - <property name="text"> - <string>float</string> - </property> - </item> - </widget> - </item> - <item row="0" column="1"> - <widget class="QComboBox" name="cbAudioDrv"/> - </item> - <item row="4" column="1"> - <widget class="QComboBox" name="cbFrequency"> - <property name="currentIndex"> - <number>2</number> - </property> - <item> - <property name="text"> - <string>22050</string> - </property> - </item> - <item> - <property name="text"> - <string>44100</string> - </property> - </item> - <item> - <property name="text"> - <string>48000</string> - </property> - </item> - <item> - <property name="text"> - <string>96000</string> - </property> - </item> - </widget> - </item> - <item row="3" column="0"> - <widget class="QLabel" name="lbFormat"> - <property name="text"> - <string>Audio Format</string> - </property> - </widget> - </item> - <item row="5" column="1"> - <widget class="QSpinBox" name="sbPolyphony"> - <property name="minimum"> - <number>1</number> - </property> - <property name="maximum"> - <number>65535</number> - </property> - <property name="value"> - <number>2048</number> - </property> - </widget> - </item> - <item row="5" column="0"> - <widget class="QLabel" name="lbPolyphony"> - <property name="text"> - <string>Max Polyphony</string> - </property> - </widget> - </item> - <item row="7" column="0"> - <widget class="QCheckBox" name="cbAutoBS"> - <property name="text"> - <string>Auto bank select mode</string> - </property> - </widget> - </item> - <item row="8" column="0"> - <widget class="QLabel" name="lbBSMode"> - <property name="text"> - <string>Bank select mode</string> - </property> - </widget> - </item> - <item row="8" column="1"> - <widget class="QComboBox" name="cbBSMode"> - <property name="currentIndex"> - <number>1</number> - </property> - <item> - <property name="text"> - <string>Ignored</string> - </property> - </item> - <item> - <property name="text"> - <string>CC#0</string> - </property> - </item> - <item> - <property name="text"> - <string>CC#32</string> - </property> - </item> - <item> - <property name="text"> - <string>CC#0*128+CC#32</string> - </property> - </item> - </widget> - </item> - <item row="6" column="0"> - <widget class="QLabel" name="lbCPUCores"> - <property name="text"> - <string>CPU Cores</string> - </property> - </widget> - </item> - <item row="6" column="1"> - <widget class="QSpinBox" name="sbCPUCores"> - <property name="minimum"> - <number>1</number> - </property> - <property name="maximum"> - <number>256</number> - </property> - </widget> - </item> - </layout> - </widget> - <widget class="QWidget" name="tab_3"> - <attribute name="title"> - <string>Soundfonts</string> - </attribute> - <layout class="QVBoxLayout" name="verticalLayout_2"> - <item> - <widget class="QListWidget" name="lwSoundfont"> - <property name="dragDropMode"> - <enum>QAbstractItemView::InternalMove</enum> - </property> - </widget> - </item> - <item> - <layout class="QHBoxLayout" name="horizontalLayout"> - <item> - <widget class="QPushButton" name="pbAdd"> - <property name="text"> - <string/> - </property> - <property name="icon"> - <iconset resource="resources.qrc"> - <normaloff>:/img/add.png</normaloff>:/img/add.png</iconset> - </property> - <property name="iconSize"> - <size> - <width>24</width> - <height>24</height> - </size> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="pbRemove"> - <property name="text"> - <string/> - </property> - <property name="icon"> - <iconset resource="resources.qrc"> - <normaloff>:/img/remove.png</normaloff>:/img/remove.png</iconset> - </property> - <property name="iconSize"> - <size> - <width>24</width> - <height>24</height> - </size> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="pbUp"> - <property name="text"> - <string/> - </property> - <property name="icon"> - <iconset resource="resources.qrc"> - <normaloff>:/img/up.png</normaloff>:/img/up.png</iconset> - </property> - <property name="iconSize"> - <size> - <width>24</width> - <height>24</height> - </size> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="pbDown"> - <property name="text"> - <string/> - </property> - <property name="icon"> - <iconset resource="resources.qrc"> - <normaloff>:/img/down.png</normaloff>:/img/down.png</iconset> - </property> - <property name="iconSize"> - <size> - <width>24</width> - <height>24</height> - </size> - </property> - </widget> - </item> - </layout> - </item> - </layout> - </widget> - <widget class="QWidget" name="tab_4"> - <attribute name="title"> - <string>Behavior</string> - </attribute> - <layout class="QVBoxLayout" name="verticalLayout_3"> - <item> - <widget class="QCheckBox" name="cbRestorePlaylist"> - <property name="text"> - <string>Restore last playlist on startup</string> - </property> - </widget> - </item> - <item> - <widget class="QCheckBox" name="cbLoadFolder"> - <property name="text"> - <string>Load files in the same folder</string> - </property> - </widget> - </item> - <item> - <widget class="QCheckBox" name="cbDialogStatus"> - <property name="text"> - <string>Save dialog status</string> - </property> - </widget> - </item> - <item> - <widget class="QCheckBox" name="cbSaveEfxParam"> - <property name="text"> - <string>Save parameters in effects window</string> - </property> - </widget> - </item> - <item> - <widget class="QCheckBox" name="cbPersistentfs"> - <property name="text"> - <string>Persistent fluidsynth instance</string> - </property> - </widget> - </item> - <item> - <layout class="QHBoxLayout" name="horizontalLayout_2"> - <item> - <widget class="QLabel" name="lbVisualMode"> - <property name="text"> - <string>Visualization Mode</string> - </property> - </widget> - </item> - <item> - <widget class="QComboBox" name="cbVisualMode"/> - </item> - </layout> - </item> - <item> - <layout class="QHBoxLayout" name="horizontalLayout_3"> - <item> - <widget class="QLabel" name="lbViewDist"> - <property name="text"> - <string>View distance</string> - </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeType"> - <enum>QSizePolicy::Expanding</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>50</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QSlider" name="hsViewDist"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> - <horstretch>60</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - </widget> - </item> - <item> - <widget class="QSpinBox" name="sbViewDist"/> - </item> - </layout> - </item> - <item> - <layout class="QHBoxLayout" name="horizontalLayout_4"> - <item> - <widget class="QLabel" name="lbNoteStretch"> - <property name="text"> - <string>Note stretch</string> - </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer_2"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeType"> - <enum>QSizePolicy::Expanding</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>60</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QSlider" name="hsNoteStretch"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> - <horstretch>60</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - </widget> - </item> - <item> - <widget class="QSpinBox" name="sbNoteStretch"/> - </item> - </layout> - </item> - <item> - <layout class="QHBoxLayout" name="horizontalLayout_5"> - <item> - <widget class="QLabel" name="lbFog"> - <property name="text"> - <string>Fog Start</string> - </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer_3"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeType"> - <enum>QSizePolicy::Expanding</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>82</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QSlider" name="hsFog"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> - <horstretch>60</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - </widget> - </item> - <item> - <widget class="QSpinBox" name="sbFog"/> - </item> - </layout> - </item> - </layout> - </widget> - </widget> - </item> - <item> - <widget class="QDialogButtonBox" name="buttonBox"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="standardButtons"> - <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> - </property> - </widget> - </item> - </layout> - </widget> - <resources> - <include location="resources.qrc"/> - </resources> - <connections> - <connection> - <sender>buttonBox</sender> - <signal>accepted()</signal> - <receiver>qmpSettingsWindow</receiver> - <slot>accept()</slot> - <hints> - <hint type="sourcelabel"> - <x>248</x> - <y>254</y> - </hint> - <hint type="destinationlabel"> - <x>157</x> - <y>274</y> - </hint> - </hints> - </connection> - <connection> - <sender>buttonBox</sender> - <signal>rejected()</signal> - <receiver>qmpSettingsWindow</receiver> - <slot>reject()</slot> - <hints> - <hint type="sourcelabel"> - <x>316</x> - <y>260</y> - </hint> - <hint type="destinationlabel"> - <x>286</x> - <y>274</y> - </hint> - </hints> - </connection> - </connections> -</ui> diff --git a/qmidiplayer.src.d/resources.qrc b/qmidiplayer.src.d/resources.qrc deleted file mode 100644 index 351d2fa..0000000 --- a/qmidiplayer.src.d/resources.qrc +++ /dev/null @@ -1,36 +0,0 @@ -<RCC> - <qresource prefix="/"> - <file>../img/add.png</file> - <file>../img/list.png</file> - <file>../img/addfolder.png</file> - <file>../img/channel.png</file> - <file>../img/prev.png</file> - <file>../img/qmidiplyr.png</file> - <file>../img/remove.png</file> - <file>../img/clear.png</file> - <file>../img/down.png</file> - <file>../img/effects.png</file> - <file>../img/repeat-all.png</file> - <file>../img/repeat-base.png</file> - <file>../img/repeat-non.png</file> - <file>../img/load.png</file> - <file>../img/next.png</file> - <file>../img/repeat-one.png</file> - <file>../img/save.png</file> - <file>../img/settings.png</file> - <file>../img/pause.png</file> - <file>../img/play.png</file> - <file>../img/shuffle-off.png</file> - <file>../img/shuffle.png</file> - <file>../img/stop.png</file> - <file>../img/up.png</file> - <file>../img/visualization.png</file> - <file>../img/mainw.png</file> - <file>../img/chanw.png</file> - <file>../doc/index.html</file> - <file>../doc/version.html</file> - <file>../doc/license.html</file> - <file>../doc/mainwindow.html</file> - <file>../doc/channeldialog.html</file> - </qresource> -</RCC> diff --git a/qmidiplayerlite.pro b/qmidiplayerlite.pro deleted file mode 100644 index be7679d..0000000 --- a/qmidiplayerlite.pro +++ /dev/null @@ -1,24 +0,0 @@ -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 deleted file mode 100644 index 265ce71..0000000 --- a/qmidiplayerlite.src.d/deployment.pri +++ /dev/null @@ -1,13 +0,0 @@ -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 deleted file mode 100644 index 1a87b33..0000000 --- a/qmidiplayerlite.src.d/main.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include <QApplication> -#include <QtQml> -#include <QQmlApplicationEngine> -#include "qmpcorewrapper.hpp" - -int main(int argc, char *argv[]) -{ - QApplication app(argc, argv); - qmlRegisterType<CQMPCoreWrapper>("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 deleted file mode 100644 index 0ec0975..0000000 --- a/qmidiplayerlite.src.d/main.qml +++ /dev/null @@ -1,144 +0,0 @@ -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 deleted file mode 100644 index 5f6483a..0000000 --- a/qmidiplayerlite.src.d/qml.qrc +++ /dev/null @@ -1,5 +0,0 @@ -<RCC> - <qresource prefix="/"> - <file>main.qml</file> - </qresource> -</RCC> diff --git a/qmidiplayerlite.src.d/qmpcorewrapper.hpp b/qmidiplayerlite.src.d/qmpcorewrapper.hpp deleted file mode 100644 index 558ed74..0000000 --- a/qmidiplayerlite.src.d/qmpcorewrapper.hpp +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef QMPCOREWRAPPER_H -#define QMPCOREWRAPPER_H -#include <QObject> -#include <QUrl> -#include <thread> -#include <fluidsynth.h> -#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 deleted file mode 100644 index baec9a2..0000000 --- a/qmidiplayerlite.src.d/qmpmidiplay.cpp +++ /dev/null @@ -1,406 +0,0 @@ -#include <cstdio> -#include <chrono> -#include <thread> -#include <fluidsynth.h> -#include "qmpmidiplay.hpp" -#ifdef _WIN32 -#include <windows.h> -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)*1000000<t*pf); -} -#endif -void CMidiPlayer::playEvents() -{ - for(uint32_t ct=midiFile->getEvent(0)->time;tceptr<midiFile->getEventCount();) - { - while(tcpaused)std::this_thread::sleep_for(std::chrono::milliseconds(100)); - while(!tcstop&&midiFile&&tceptr<midiFile->getEventCount()&&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;eptr<midiFile->getEventCount();) - { - while(eptr<midiFile->getEventCount()&&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;eptr<midiFile->getEventCount();) - { - while(eptr<midiFile->getEventCount()&&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<<bn);} -void CMidiPlayer::setMute(int ch,bool m) -{setBit(mute,ch,m?1:0);} -void CMidiPlayer::setSolo(int ch,bool s) -{setBit(solo,ch,s?1:0);} -int CMidiPlayer::getCC(int ch, int id) -{int ret=0;synth?fluid_synth_get_cc(synth,ch,id,&ret):0;return ret;} -void CMidiPlayer::setCC(int ch, int id, int val) -{synth?fluid_synth_cc(synth,ch,id,val):0;} -void CMidiPlayer::getReverbPara(double *r,double *d,double *w,double *l) -{ - if(!synth)return; - *r=fluid_synth_get_reverb_roomsize(synth); - *d=fluid_synth_get_reverb_damp(synth); - *w=fluid_synth_get_reverb_width(synth); - *l=fluid_synth_get_reverb_level(synth); -} -void CMidiPlayer::setReverbPara(int e,double r,double d,double w,double l) -{ - if(!synth)return; - fluid_synth_set_reverb_on(synth,e); - fluid_synth_set_reverb(synth,r,d,w,l); -} -void CMidiPlayer::getChorusPara(int *fb,double *l,double *r,double *d,int *type) -{ - if(!synth)return; - *fb=fluid_synth_get_chorus_nr(synth); - *l=fluid_synth_get_chorus_level(synth); - *r=fluid_synth_get_chorus_speed_Hz(synth); - *d=fluid_synth_get_chorus_depth_ms(synth); - *type=fluid_synth_get_chorus_type(synth); -} -void CMidiPlayer::setChorusPara(int e,int fb,double l,double r,double d,int type) -{ - if(!synth)return; - fluid_synth_set_chorus_on(synth,e); - fluid_synth_set_chorus(synth,fb,l,r,d,type); -} -fluid_settings_t* CMidiPlayer::getFluidSettings(){return settings;} -void CMidiPlayer::pushSoundFont(const char *sf) -{fluid_synth_sfload(synth,sf,1);} -int CMidiPlayer::getSFCount() -{return synth?fluid_synth_sfcount(synth):0;} -fluid_sfont_t* CMidiPlayer::getSFPtr(int sfid) -{return synth&&sfid<getSFCount()?fluid_synth_get_sfont(synth,sfid):NULL;} diff --git a/qmidiplayerlite.src.d/qmpmidiplay.hpp b/qmidiplayerlite.src.d/qmpmidiplay.hpp deleted file mode 100644 index fafd677..0000000 --- a/qmidiplayerlite.src.d/qmpmidiplay.hpp +++ /dev/null @@ -1,137 +0,0 @@ -//sorry for the stupid C-like code... -#ifndef QMPMIDIPLAY_H -#define QMPMIDIPLAY_H -#include <cstring> -#include <cstdint> -#include <cstdlib> -#include <fluidsynth.h> -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 deleted file mode 100644 index 0bcf597..0000000 --- a/qmidiplayerlite.src.d/qmpmidiread.cpp +++ /dev/null @@ -1,240 +0,0 @@ -//CLI Midi file player based on libfluidsynth -//Midi file reading module -//Written by Chris Xiong, 2015 -#include <cstdio> -#include <cstring> -#include <cstdlib> -#include <cstdint> -#include <cstdarg> -#include <algorithm> -#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->time<b->time:a->iid<b->iid;} -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;c<len;++c) - { - ++byteread;if(str)str[c]=fgetc(f);else fgetc(f); - } - if(str)str[c]='\0';eventList[eventc++]=new SEvent(curid,curt,type,metatype,0,str); - if(str&&metatype==0x03&&!title) - { - title=new char[len+8]; - strcpy(title,str); - } - if(str&&metatype==0x02&&!copyright) - { - copyright=new char[len+8]; - strcpy(copyright,str); - } - if(len<=1024&&len>0)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;c<len;++c){++byteread;str[c]=fgetc(f);} - } - else for(c=0;c<len;++c){++byteread;str[c]=fgetc(f);} - eventList[eventc++]=new SEvent(curid,curt,type,len,0,str); - if(!strcmp(str,GM1SysX))std=1; - if(!strcmp(str,GM2SysX))std=2; - if(!strcmp(str,GSSysEx))std=3; - if(!strcmp(str,XGSysEx))std=4; - } - else error(0,"W: Unknown event type %#x",type); - break; - default: - fseek(f,-1,SEEK_CUR);--byteread;type=lasttype;goto retry; - } - lasttype=type;++curid; - return 1; -} -void CMidiFile::trackChunkReader() -{ - int chnklen=readDW();byteread=0;curt=0;curid=0; - while(/*byteread<chnklen&&*/eventReader()); - if(byteread<chnklen) - { - error(0,"W: Extra bytes after EOT event."); - while(byteread<chnklen){fgetc(f);++byteread;} - } - /*if(byteread>chnklen) - { - 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(;byteread<chnklen;++byteread){fgetc(f);} -} -int CMidiFile::chunkReader(int hdrXp) -{ - char hdr[6]; - if(!fgets(hdr,5,f))error(1,"E: Unexpected EOF."); - if(hdrXp) - if(strncmp(hdr,"MThd",4)){error(1,"E: Wrong MIDI header.");throw;} - else return headerChunkReader(),0; - else - if(strncmp(hdr,"MTrk",4)) - { - error(0,"W: Wrong track chunk header. Ignoring the whole chunk."); - for(int chnklen=readDW();chnklen>0;--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<trk;i+=chunkReader(0)); - printf("%d note(s)\n",notes); - fclose(f); - std::sort(eventList,eventList+eventc,cmp); - } - catch(int){fprintf(stderr,"E: %s is not a supported file.\n",fn);valid=0;} -} -CMidiFile::~CMidiFile() -{ - for(uint32_t i=0;i<eventc;++i)delete eventList[i]; - if(title)delete[] title;if(copyright)delete[] copyright; -} -const SEvent* CMidiFile::getEvent(uint32_t id){return id<eventc?eventList[id]:NULL;} -uint32_t CMidiFile::getEventCount(){return eventc;} -uint32_t CMidiFile::getDivision(){return divs;} -uint32_t CMidiFile::getNoteCount(){return notes;} -uint32_t CMidiFile::getStandard(){return std;} -bool CMidiFile::isValid(){return valid;} -const char* CMidiFile::getTitle(){return title;} -const char* CMidiFile::getCopyright(){return copyright;} -- cgit v1.2.3