853 lines
16 KiB
C++
853 lines
16 KiB
C++
|
#include "main.h"
|
||
|
#include "seq.h"
|
||
|
#include <commctrl.h>
|
||
|
#include <math.h>
|
||
|
#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<<ch;
|
||
|
seq_shortmsg(0x07B0|ch);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
mute_mask&=~(1<<ch);
|
||
|
SEND_MSG(((DWORD)ctrl_tab[ch][7]<<16)|0x07B0|ch);
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
//debug hack
|
||
|
#if 0
|
||
|
#define timeGetTime timehack
|
||
|
static DWORD timehack()
|
||
|
{
|
||
|
static DWORD t;
|
||
|
return t++;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
DWORD seq_base::get_time()
|
||
|
{
|
||
|
#ifndef SEQ_HAVE_PANEL
|
||
|
return timeGetTime()<<3;
|
||
|
#else
|
||
|
if (!hCtrl) return timeGetTime()<<3;//*8;
|
||
|
EnterCriticalSection(&tm_sec);
|
||
|
DWORD cur_t=timeGetTime();
|
||
|
if (!last_time_ms) last_time_ms=cur_t;
|
||
|
int d=cur_t-last_time_ms;
|
||
|
if (d<0) d=0;
|
||
|
last_time_ret+=(double)(d*8.0)*tempo;
|
||
|
|
||
|
last_time_ms=cur_t;
|
||
|
DWORD r=(DWORD)last_time_ret;
|
||
|
LeaveCriticalSection(&tm_sec);
|
||
|
return r;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
#ifdef SEQ_HAVE_PANEL
|
||
|
BOOL CALLBACK seq_base::CtrlProc(HWND wnd,UINT msg,WPARAM wp,LPARAM lp)
|
||
|
{
|
||
|
seq_base* s;
|
||
|
if (msg==WM_INITDIALOG)
|
||
|
{
|
||
|
SetWindowLongPtr(wnd,DWLP_USER,lp);
|
||
|
s=(seq_base*)lp;
|
||
|
if (s) s->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<<n))
|
||
|
{
|
||
|
SendDlgItemMessage(hCtrl,MUTE_ID+n,BM_SETCHECK,0,0);
|
||
|
set_mute(n,0);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if (wp==IDC_ALL_OFF)
|
||
|
{
|
||
|
UINT n;
|
||
|
for(n=0;n<16;n++)
|
||
|
{
|
||
|
if (!(mute_mask&(1<<n)))
|
||
|
{
|
||
|
SendDlgItemMessage(hCtrl,MUTE_ID+n,BM_SETCHECK,1,0);
|
||
|
set_mute(n,1);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if (wp==IDC_GMRESET)
|
||
|
{
|
||
|
rsysex(d_GMReset);
|
||
|
}
|
||
|
else if (wp==IDC_GSRESET)
|
||
|
{
|
||
|
rsysex(d_GSReset);
|
||
|
}
|
||
|
else if (wp==IDC_XGRESET)
|
||
|
{
|
||
|
rsysex(d_XGReset);
|
||
|
}
|
||
|
else for(n=0;n<16;n++)
|
||
|
{
|
||
|
if (wp==MUTE_ID+n)
|
||
|
{
|
||
|
set_mute(n,SendMessage((HWND)lp,BM_GETCHECK,0,0));
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if (HIWORD(wp)==EN_CHANGE)
|
||
|
{
|
||
|
if (initialized)
|
||
|
{
|
||
|
wp&=0xFFFF;
|
||
|
UINT n;
|
||
|
for(n=0;n<16;n++)
|
||
|
{
|
||
|
if (wp==INS_ID_P+n)
|
||
|
{
|
||
|
UINT p=GetDlgItemInt(hCtrl,wp,0,0)&0x7F;
|
||
|
if (p!=ins_tab[n])
|
||
|
{
|
||
|
ins_tab[n]=p;
|
||
|
SEND_MSG(0xC0|n|(p<<8));
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
else if (wp==INS_ID_B1+n)
|
||
|
{
|
||
|
UINT p=GetDlgItemInt(hCtrl,wp,0,0)&0x7F;
|
||
|
if (p!=ctrl_tab[n][0])
|
||
|
{
|
||
|
ctrl_tab[n][0]=p;
|
||
|
SEND_MSG(0xB0|n|(p<<16));
|
||
|
SEND_MSG(0xC0|n|(ins_tab[n]<<8));
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
else if (wp==INS_ID_B2+n)
|
||
|
{
|
||
|
UINT p=GetDlgItemInt(hCtrl,wp,0,0)&0x7F;
|
||
|
if (p!=ctrl_tab[n][0x20])
|
||
|
{
|
||
|
ctrl_tab[n][0x20]=p;
|
||
|
SEND_MSG(0x20B0|n|(p<<16));
|
||
|
SEND_MSG(0xC0|n|(ins_tab[n]<<8));
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
break;
|
||
|
case WM_VSCROLL:
|
||
|
{
|
||
|
HWND sb=(HWND)lp;
|
||
|
if (sb)
|
||
|
{
|
||
|
UINT id=GetWindowLong(sb,GWL_ID);
|
||
|
UINT n;
|
||
|
for(n=0;n<16;n++)
|
||
|
{
|
||
|
if (id==VOL_ID+n)
|
||
|
{
|
||
|
UINT val=0x7f-SendMessage(sb,TBM_GETPOS,0,0);
|
||
|
ctrl_tab[n][7]=val;
|
||
|
SEND_MSG(0x7B0|n|(val<<16));
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
case WM_HSCROLL:
|
||
|
tempo=ui2tempo(SendDlgItemMessage(hCtrl,IDC_TEMPO,TBM_GETPOS,0,0));
|
||
|
do_ttext(hCtrl,tempo);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
seq_base::~seq_base()
|
||
|
{
|
||
|
#ifdef SEQ_HAVE_PANEL
|
||
|
if (hCtrl)
|
||
|
{
|
||
|
cfg_ctrl_min=!!IsIconic(hCtrl);
|
||
|
RECT r;
|
||
|
GetWindowRect(hCtrl,&r);
|
||
|
cfg_ctrl_x=r.left;
|
||
|
cfg_ctrl_y=r.top;
|
||
|
GetDlgItemTextA(hCtrl,IDC_SYSEX1,sysex1,256);
|
||
|
GetDlgItemTextA(hCtrl,IDC_SYSEX2,sysex2,256);
|
||
|
DestroyWindow(hCtrl);
|
||
|
DeleteCriticalSection(&tm_sec);
|
||
|
}
|
||
|
g_tempo=tempo;
|
||
|
g_novol=novol;
|
||
|
g_noins=noins;
|
||
|
#endif
|
||
|
if (events) free(events);
|
||
|
}
|
||
|
|
||
|
seq_base::seq_base()
|
||
|
{
|
||
|
mf=0;
|
||
|
|
||
|
kill=0;paused=0;
|
||
|
smap=0;
|
||
|
|
||
|
pan=0;vol=0;
|
||
|
|
||
|
seek_to=0;
|
||
|
n_events=0;
|
||
|
events=0;
|
||
|
|
||
|
c_loop=0;
|
||
|
loop_start=0;
|
||
|
memset(¬es,0,sizeof(notes));
|
||
|
memset(&ctrl_tab,0,sizeof(ctrl_tab));
|
||
|
memset(&ins_tab,0,sizeof(ins_tab));
|
||
|
|
||
|
tm_ofs=0;
|
||
|
p_time=0;
|
||
|
hTrd=0;
|
||
|
|
||
|
ins_set=0;
|
||
|
|
||
|
#ifdef SEQ_HAVE_PANEL
|
||
|
hCtrl=0;
|
||
|
|
||
|
tempo=g_tempo;
|
||
|
novol=g_novol;
|
||
|
noins=g_noins;
|
||
|
|
||
|
last_time_ms=0;
|
||
|
last_time_ret=0;
|
||
|
|
||
|
mute_mask=0;
|
||
|
initialized=0;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
|
||
|
#define GET_TIME get_time()//timeGetTime()
|
||
|
|
||
|
int IS_SPEC_C(int x) {return (x>=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<<ch)))
|
||
|
{
|
||
|
SEND_MSG(0xC0|ch);
|
||
|
}
|
||
|
}
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
void seq_base::reset()
|
||
|
{
|
||
|
int not,ch;
|
||
|
for(ch=0;ch<16;ch++)
|
||
|
{
|
||
|
if (ctrl_tab[ch][0x40])
|
||
|
{
|
||
|
seq_shortmsg(0x40B0|ch);
|
||
|
ctrl_tab[ch][0x40]=0;
|
||
|
}
|
||
|
if (ch==9) continue;
|
||
|
for(not=0;not<128;not++)
|
||
|
{
|
||
|
if (note_state(ch,not))
|
||
|
{
|
||
|
seq_shortmsg((not<<8)|0x80|ch);
|
||
|
note_off(ch,not);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
int seq_base::note_state(int ch,int note)
|
||
|
{
|
||
|
UINT pos=(ch<<7)+note;
|
||
|
return notes[pos>>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(n<n_events && p>events[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<n_events && events[pos].tm<=c_t && !kill)
|
||
|
{
|
||
|
DWORD e=events[pos++].ev;
|
||
|
if (e)
|
||
|
{
|
||
|
if (e&0x80000000)
|
||
|
{
|
||
|
send_sysex(e&0x7FFFFFFF);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if ((e&0xF0)==0x90)
|
||
|
{
|
||
|
note_on(e&0xf,(e>>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<n_events;n++)
|
||
|
{
|
||
|
DWORD t=events[n].ev;
|
||
|
if (t&0xFF000000) continue;
|
||
|
UINT c=t&0xF0;
|
||
|
UINT ch=events[n].ev&0xF;
|
||
|
if ((t&0xFFF0)==0x20B0)
|
||
|
{
|
||
|
c_ins[ch]=(c_ins[ch]&0xFFFF00FF)|((t>>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:;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
*/
|