From 20d28e80a5c861a9d5f449ea911ab75b4f37ad0d Mon Sep 17 00:00:00 2001 From: Jef Date: Tue, 24 Sep 2024 14:54:57 +0200 Subject: Initial community commit --- Src/Plugins/Input/in_midi/seq.cpp | 852 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 852 insertions(+) create mode 100644 Src/Plugins/Input/in_midi/seq.cpp (limited to 'Src/Plugins/Input/in_midi/seq.cpp') diff --git a/Src/Plugins/Input/in_midi/seq.cpp b/Src/Plugins/Input/in_midi/seq.cpp new file mode 100644 index 00000000..f1fb65fb --- /dev/null +++ b/Src/Plugins/Input/in_midi/seq.cpp @@ -0,0 +1,852 @@ +#include "main.h" +#include "seq.h" +#include +#include +#include "resource.h" + +#ifdef SEQ_HAVE_PANEL + +cfg_int cfg_seq_showpanel("seq_showpanel",0); + +enum +{ + ID_BASE = 0x6543, + MUTE_ID = ID_BASE, + VOL_ID = MUTE_ID+16, + INS_ID_P = VOL_ID+16, + INS_ID_B1 = INS_ID_P+16, + INS_ID_B2 = INS_ID_B1+16, + SPIN_ID = INS_ID_B2 + +}; + +static cfg_int cfg_ctrl_min("ctrl_min",0); + + +static float g_tempo=1; +static BOOL g_novol,g_noins; +static char sysex1[256],sysex2[256]; + +extern BYTE d_GMReset[6]; +extern BYTE d_XGReset[9]; +extern BYTE d_GSReset[11]; +#endif + +#define SEND_MSG(X) seq_shortmsg(preprocess(X)) + +#define _sysex(A,B) seq_sysex(A,B) +#define rsysex(A) seq_sysex(A,sizeof(A)) + +#ifdef SEQ_HAVE_PANEL +void seq_base::set_mute(UINT ch,BOOL st) +{ + if (st) + { + mute_mask|=1<hCtrl=wnd; + } + else + { +#if defined(_WIN64) + s = (seq_base*)GetWindowLong(wnd, DWLP_USER); +#else + s = (seq_base*)GetWindowLong(wnd, DWL_USER); +#endif + } + if (s) + { + s->do_msg(msg,wp,lp); + } + return 0; +} + +static float ui2tempo(int x) +{ + return (float)pow(4.0,0.02*(float)(x-50)); +} + +static int tempo2ui(float x) +{ + return 50+(int) ((50.0 / log(4.0)) * log(x) ); +} + +static void do_ttext(HWND w,float t) +{ + char tx[32] = {0}; + _itoa((UINT)(t*100.0),tx,10); + char* p=tx; + while(p && *p) p++; + *(p++)='%'; + *p=0; + SetDlgItemTextA(w,IDC_TDISP,tx); +} + +BYTE* read_sysex_edit(HWND w,UINT *siz); + +void CreateControl(DWORD ex,HWND hCtrl,const char * cls,const char * name,DWORD style,UINT x,UINT y,UINT dx,UINT dy,HINSTANCE hDll,UINT id) +{ + RECT r={(LONG)x,(LONG)y,(LONG)(x+dx),(LONG)(y+dy)}; + MapDialogRect(hCtrl,&r); + HWND w = CreateWindowExA( ex, cls, name, WS_CHILD | WS_VISIBLE | style, r.left, r.top, r.right - r.left, r.bottom - r.top, hCtrl, 0, hDll, 0 ); // Must stay in ANSI + if (w) + { + if (id) SetWindowLong(w,GWL_ID,id); + SendMessage(w,WM_SETFONT,SendMessage(hCtrl,WM_GETFONT,0,0),MAKELONG(0,0)); + } +} + +static cfg_int cfg_ctrl_x("ctrl_x",0x80000000),cfg_ctrl_y("ctrl_y",0x80000000); + +void seq_base::do_msg(UINT msg,WPARAM wp,LPARAM lp) +{ + switch(msg) + { + case WM_CLOSE: + ShowWindow(hCtrl,SW_SHOWMINIMIZED); + break; + case WM_INITDIALOG: + { + HINSTANCE hCCdll=GetModuleHandle(TEXT("comctl32.dll")); + UINT n; + HWND w; + for(n=0;n<16;n++) + { + char tmp[16] = {0}; + itoa(n,tmp,10); + CreateControl(0,hCtrl,TRACKBAR_CLASSA,0,TBS_VERT | TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,40+n*28,36,18,80,hCCdll,VOL_ID+n); + CreateControl(0,hCtrl,"STATIC",tmp,0,46+n*28,25,8,8,0,0); + CreateControl(0,hCtrl,"Button",0,BS_AUTOCHECKBOX | WS_TABSTOP,43+28*n,120,9,8,0,MUTE_ID+n); + CreateControl(WS_EX_CLIENTEDGE,hCtrl,"EDIT",0,ES_AUTOHSCROLL | ES_NUMBER,36+28*n,138,26,12,0,INS_ID_P+n); + CreateControl(0,hCtrl,"msctls_updown32",0,UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,0,0,0,0,0,SPIN_ID+n); + CreateControl(WS_EX_CLIENTEDGE,hCtrl,"EDIT",0,ES_AUTOHSCROLL | ES_NUMBER,36+28*n,150,26,12,0,INS_ID_B1+n); + CreateControl(0,hCtrl,"msctls_updown32",0,UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,0,0,0,0,0,SPIN_ID+n+16); + CreateControl(WS_EX_CLIENTEDGE,hCtrl,"EDIT",0,ES_AUTOHSCROLL | ES_NUMBER,36+28*n,162,26,12,0,INS_ID_B2+n); + CreateControl(0,hCtrl,"msctls_updown32",0,UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,0,0,0,0,0,SPIN_ID+n+32); + } + + w=GetDlgItem(hCtrl,IDC_TEMPO); + SendMessage(w,TBM_SETRANGE,0,MAKELONG(0,100)); + SendMessage(w,TBM_SETPOS,1,tempo2ui(tempo)); + do_ttext(hCtrl,tempo); + if (cfg_ctrl_x!=0x80000000 && cfg_ctrl_y!=0x80000000) + { + int max_x=GetSystemMetrics(SM_CXSCREEN)-10,max_y=GetSystemMetrics(SM_CYSCREEN)-10; + if (cfg_ctrl_x>max_x) cfg_ctrl_x=max_x; + if (cfg_ctrl_y>max_y) cfg_ctrl_y=max_y; + SetWindowPos(hCtrl,0,cfg_ctrl_x,cfg_ctrl_y,0,0,SWP_NOZORDER|SWP_NOSIZE); + } + for(n=0;n<16;n++) + { + w=GetDlgItem(hCtrl,VOL_ID+n); + SendMessage(w,TBM_SETRANGE,1,MAKELONG(0,0x7f)); + SendMessage(w,TBM_SETPOS,1,0x7f-90); + } + SendDlgItemMessage(hCtrl,IDC_NOVOL,BM_SETCHECK,novol,0); + SetDlgItemTextA(hCtrl,IDC_SYSEX1,sysex1); + SetDlgItemTextA(hCtrl,IDC_SYSEX2,sysex2); + for(n=0;n<48;n++) + { + SendDlgItemMessage(hCtrl,SPIN_ID+n,UDM_SETRANGE,0,MAKELONG(127,0)); + } + for(n=0;n<16;n++) + { + SendDlgItemMessage(hCtrl,INS_ID_P+n,EM_LIMITTEXT,3,0); + SendDlgItemMessage(hCtrl,INS_ID_B1+n,EM_LIMITTEXT,3,0); + SendDlgItemMessage(hCtrl,INS_ID_B2+n,EM_LIMITTEXT,3,0); + } + initialized=1; + } + break; + case WM_COMMAND: + { + UINT n; + if (HIWORD(wp)==0) + { + if (wp==IDC_SYSEX1_SEND || wp==IDC_SYSEX2_SEND) + { + UINT sl; + BYTE* s=read_sysex_edit(GetDlgItem(hCtrl,(wp==IDC_SYSEX1_SEND)?IDC_SYSEX1:IDC_SYSEX2) , &sl); + if (s) + { + _sysex(s,sl); + free(s); + } + } + else if (wp==IDC_NOVOL) + { + novol=SendMessage((HWND)lp,BM_GETCHECK,0,0); + } + else if (wp==IDC_NOINS) + { + noins=SendMessage((HWND)lp,BM_GETCHECK,0,0); + } + else if (wp==IDC_ALL_ON) + { + UINT n; + for(n=0;n<16;n++) + { + if (mute_mask&(1<=0x60 && x<=0x65) || x==6 || x==26 || x>=120;} + +#define n_sysex smap->pos + + +DWORD seq_base::preprocess(DWORD e) +{ + BYTE t=(BYTE)(e&0xF0); + if (t==0xB0) + { + UINT v=(e>>16)&0xFF; + BYTE c=(BYTE)(e>>8); +#ifdef SEQ_HAVE_PANEL + if (c==7) + { + if (mute_mask&(1<<(e&0xF))) v=0; + } +#endif + e=(e&0xFFFF)|((v&0xFF)<<16); + } + else if (t==0xC0) + { + ins_set|=1<<(e&0xF); + } + return e; +} + +void seq_base::send_sysex(int n) +{ +#ifdef USE_LOG + log_write("send_sysex()"); +#endif + if (!smap || n>=n_sysex) return; + _sysex(smap->data+smap->events[n].ofs,smap->events[n].len); +} + +/* +void seq_base::reset_ins() +{ + UINT n; + for(n=0;n<16;n++) + { + cb->shortmsg(0xC0|n); + } +} +*/ + +BOOL seq_base::do_ctrl(DWORD e) +{ + BYTE tp=(BYTE)(e&0xF0); + BYTE ch=(BYTE)(e&0x0F); + if (tp==0xC0) + { +#ifdef SEQ_HAVE_PANEL + if (noins) return 0; +#endif + //if (!cfg_fctrl && (e>>8)==ins_tab[e&0xF]) return 0; + UINT val=e>>8; + ins_tab[ch]=val; +#ifdef SEQ_HAVE_PANEL + if (hCtrl) SetDlgItemInt(hCtrl,INS_ID_P+ch,val,0); +#endif + } else if (tp==0xB0) + { + UINT cn = (e>>8)&0x7F; + UINT val= (e>>16)&0x7F; +#ifdef SEQ_HAVE_PANEL + if (cn==0) + { + if (noins) return 0; + if (hCtrl) SetDlgItemInt(hCtrl,INS_ID_B1+ch,val,0); + } + else if (cn==0x20) + { + if (noins) return 0; + if (hCtrl) SetDlgItemInt(hCtrl,INS_ID_B2+ch,val,0); + } + else if (cn==7) + { + if (novol) return 0; + if (hCtrl) PostMessage(GetDlgItem(hCtrl,VOL_ID+(e&0xF)),TBM_SETPOS,1,0x7F-val); + } + else if (cn==0x27) + { + if (novol) return 0; + } +#endif + if (!IS_SPEC_C(cn)) ctrl_tab[e&0xF][cn]=val; + } + else if (tp==0x90) + { + if (!(ins_set&(1<>3]&(1<<(pos&0x7)); +} + +void seq_base::note_on(int ch,int note) +{ + UINT pos=(ch<<7)+note; + notes[pos>>3]|=(1<<(pos&0x7)); +} + +void seq_base::note_off(int ch,int note) +{ + UINT pos=(ch<<7)+note; + notes[pos>>3]&=~(1<<(pos&0x7)); +} + +UINT seq_base::do_seek(DWORD n,DWORD p) +{ + UINT m,c; + BYTE _ctrl_tab[16][128] = {0}; + BYTE _ins_tab[16] = {0}; + memcpy(_ctrl_tab,ctrl_tab,sizeof(_ctrl_tab)); + memcpy(_ins_tab,ins_tab,sizeof(_ins_tab)); + + if (n==0) + { + memset(ins_tab,0,sizeof(ins_tab)); + for(m=0;m<16;m++) + { + _ctrl_tab[m][0]=_ctrl_tab[m][0x20]=0; + } + } + + while(nevents[n].tm) + { + DWORD e=events[n].ev; + if (!(e&0x80000000)) + { + if (do_ctrl(e)) + { + if (((e&0xF0)==0xB0) && IS_SPEC_C((e>>8)&0xFF)) + { + seq_shortmsg(e); + } + } + } + n++; + } + for(c=0;c<16;c++) + { + for(m=0;m<128;m++) + { + if (!IS_SPEC_C(m) && _ctrl_tab[c][m]!=ctrl_tab[c][m]) + { + SEND_MSG(((DWORD)ctrl_tab[c][m]<<16)|(m<<8)|0xB0|c); + } + } + if (_ins_tab[c]!=ins_tab[c]) + { + SEND_MSG(((DWORD)ins_tab[c]<<8)|0xC0|c); + } + } + return n; +} + +DWORD WINAPI seq_base::seq_trd(void* p) +{ + ((seq_base*)p)->thread(); + return 0; +} + +void seq_base::sysexfunc(seq_base* cb,BYTE* s,UINT sz) +{ + cb->seq_sysex(s,sz); +} + +void seq_base::thread() +{ + tm_ofs=-1; + if (seq_play_start()) + { + + sysex_startup((SYSEXFUNC)sysexfunc,this); + + tm_ofs=GET_TIME; + DWORD pos=0; + while(!kill) + { + DWORD c_t=GET_TIME-tm_ofs; + if (paused) + { + reset(); + while(paused && !kill) MIDI_callback::Idle(); + if (kill) break; + tm_ofs=GET_TIME-c_t; + } + + if (seek_to!=-1) + { +_seek: + DWORD _p=seek_to > c_t ? pos : 0; + c_t=seek_to; + seek_to=-1; + tm_ofs=GET_TIME-c_t; + reset(); + pos=c_t ? do_seek(_p,c_t) : 0; + } + if (events[pos].tm+1600 < c_t) + { + reset(); + pos=do_seek(pos,c_t); + } + while(pos>8)&0xFF); + } + else if ((e&0xF0)==0x80) + { + note_off(e&0xf,(e>>8)&0xFF); + } + if (do_ctrl(e)) + SEND_MSG(e); + } + } + } + + if (pos>=n_events || c_t >= events[n_events-1].tm) + { + if (loop_start!=-1 && (--c_loop)) + { + c_t=loop_start; + tm_ofs=GET_TIME-c_t; + pos=do_seek(0,c_t); + continue; + } + if (cfg_eof_delay) + { + DWORD t=timeGetTime(); + do + { + MIDI_callback::Idle(); + } while(!kill && seek_to==-1 && t+cfg_eof_delay>timeGetTime()); + if (seek_to!=-1) { + pos=0; + goto _seek; + } + } + if (!kill) MIDI_core::Eof(); + break; + } + if (kill) break; + + MIDI_callback::Idle(); + } + reset(); + } + seq_play_stop(); +} + +int seq_base::gettime() +{ + if (paused) + return (seek_to==-1) ? seek_to>>3 : p_time; + else + return (GET_TIME-tm_ofs)>>3; +} + +int seq_base::settime(int tm) +{ + seek_to=tm<<3; + return 1; +} + + +void seq_base::pause() +{ + paused=1; + p_time=GET_TIME-tm_ofs; +} + +void seq_base::unpause() +{ + paused=0; +} + +int seq_base::seq_cmd_start(DWORD cflags) +{ + mf=MIDI_core::getFile(); +#ifdef SEQ_HAVE_PANEL + mute_mask=0; +#endif + c_loop=cfg_loop_infinite ? -1 : cfg_loop_count; + memset(notes,0,sizeof(notes)); + memset(ctrl_tab,-1,sizeof(ctrl_tab)); + memset(ins_tab,0,sizeof(ins_tab)); + + UINT n; + for(n=0;n<16;n++) ctrl_tab[n][7]=90; + + events=do_table(mf,8,&n_events,&loop_start,cflags); + if (!events) return 0; + + if (!cfg_nosysex && mf->smap && mf->smap->pos) + { + smap=mf->smap; + } + else smap=0; + + kill=0; + seek_to=-1; + paused=0; + +#ifdef SEQ_HAVE_PANEL + if (cfg_seq_showpanel) + { + InitializeCriticalSection(&tm_sec); + WASABI_API_CREATEDIALOGPARAMW(IDD_EXT_IMM, MIDI_callback::GetMainWindow(), CtrlProc, (LPARAM)this); + ShowWindow(hCtrl,cfg_ctrl_min ? SW_SHOWMINIMIZED : SW_SHOW); + } + else + { + tempo=1; + novol=0; + noins=0; + } +#endif + + DWORD id; + hTrd=CreateThread(0,0,seq_trd,this,CREATE_SUSPENDED,&id); +#ifndef _DEBUG + SetThreadPriority(hTrd,THREAD_PRIORITY_TIME_CRITICAL); +#endif + ResumeThread(hTrd); + return 1; +} + +void seq_base::seq_cmd_stop() +{ +#ifdef USE_LOG + log_write("stopping sequencer"); +#endif + if (hTrd) + { +#ifdef USE_LOG + log_write("killing thread"); +#endif + kill=1; + if (WaitForSingleObject(hTrd,4000)!=WAIT_OBJECT_0) + { +#ifdef USE_LOG + log_write("unable to kill thread"); +#endif + TerminateThread(hTrd,0); + } +#ifdef USE_LOG + else log_write("thread killed normally"); +#endif + CloseHandle(hTrd); + } +} +/* +void seq_base::enum_ins() +{ + DWORD ttab[256]; + memset(ttab,-1,sizeof(ttab)); + UINT tpt=0; + UINT n; + DWORD c_ins[16]; + memset(c_ins,0,sizeof(c_ins)); + c_ins[9]=0x80000000; + for(n=0;n>8)&0xFF00); + } + else if ((t&0xFFF0)==0xB0) + { + c_ins[ch]=(c_ins[ch]&0xFF00FFFF)|(t&0xFF0000); + } + else if ((t&0xF0)==0xC0) + { + c_ins[ch]=(c_ins[ch]&0xFFFFFF00)|((t>>8)&0xFF); + } + else if ((t&0xF0)==0x90) + { + UINT n; + for(n=0;n<256;n++) + { + if (ttab[n]==c_ins[ch]) goto ok; + } + cb->enum_ins(ttab[tpt]=c_ins[ch]); + tpt=(tpt+1)&0xFF; +ok:; + } + } +} +*/ -- cgit