utils.cpp 19 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064
  1. #include "main.h"
  2. #include "../Agave/language/api_language.h"
  3. #include <commdlg.h>
  4. #include "resource.h"
  5. DWORD _fastcall rev32(DWORD d) {return _rv(d);}
  6. void CPipe::WriteData(void* b,UINT s)
  7. {
  8. if (closed) return;
  9. sec.enter();
  10. if (buf_n+s>buf_s)
  11. {
  12. #ifdef USE_LOG
  13. log_write("buffer overflow");
  14. #endif
  15. s=buf_s-buf_n;
  16. s-=s%align;
  17. }
  18. if (s)
  19. {
  20. if (buf_wp+s<buf_s)
  21. {
  22. memcpy(buf+buf_wp,b,s);
  23. buf_wp+=s;
  24. }
  25. else
  26. {
  27. UINT d=buf_s-buf_wp;
  28. memcpy(buf+buf_wp,b,d);
  29. memcpy(buf,(BYTE*)b+d,s-d);
  30. buf_wp=s-d;
  31. }
  32. buf_n+=s;
  33. }
  34. sec.leave();
  35. }
  36. UINT CPipe::ReadData(void* _b,UINT s,bool* ks)
  37. {
  38. UINT rv=0;
  39. BYTE * b=(BYTE*)_b;
  40. sec.enter();
  41. while(1)
  42. {
  43. UINT d=s;
  44. if (d>buf_n) d=buf_n;
  45. if (d)
  46. {
  47. if (buf_rp+d<buf_s)
  48. {
  49. memcpy(b,buf+buf_rp,d);
  50. buf_rp+=d;
  51. }
  52. else
  53. {
  54. UINT d1=buf_s-buf_rp;
  55. memcpy(b,buf+buf_rp,d1);
  56. memcpy(b+d1,buf,d-d1);
  57. buf_rp=d-d1;
  58. }
  59. buf_n-=d;
  60. s-=d;
  61. rv+=d;
  62. b+=d;
  63. }
  64. if (closed || !s || *ks) break;
  65. sec.leave();
  66. MIDI_callback::Idle();
  67. sec.enter();
  68. }
  69. sec.leave();
  70. return rv;
  71. }
  72. #ifdef USE_LOG
  73. static HANDLE hLog;
  74. void log_start()
  75. {
  76. hLog=CreateFile("c:\\in_midi.log",GENERIC_WRITE,FILE_SHARE_READ,0,OPEN_ALWAYS,0,0);
  77. SetFilePointer(hLog,0,0,FILE_END);
  78. log_write("opening log");
  79. }
  80. void log_quit() {log_write("closing log");log_write("");log_write("");CloseHandle(hLog);}
  81. void log_write(char* t)
  82. {
  83. DWORD bw;
  84. WriteFile(hLog,t,strlen(t),&bw,0);
  85. char _t[2]={13,10};
  86. WriteFile(hLog,_t,2,&bw,0);
  87. FlushFileBuffers(hLog);
  88. }
  89. #endif
  90. //tempo map object
  91. CTempoMap* tmap_create()
  92. {
  93. CTempoMap* m=new CTempoMap;
  94. if (m)
  95. {
  96. m->pos=0;
  97. m->size=0x100;
  98. m->data=(TMAP_ENTRY*)malloc(m->size*sizeof(TMAP_ENTRY));
  99. }
  100. return m;
  101. }
  102. void CTempoMap::AddEntry(int _p,int tm)
  103. {
  104. if (!data) {pos=size=0;return;}
  105. if (pos && _p<=data[pos-1].pos) {data[pos-1].tm=tm;return;}
  106. if (pos==size)
  107. {
  108. size*=2;
  109. data=(TMAP_ENTRY*)realloc(data,size*sizeof(TMAP_ENTRY));
  110. if (!data) {pos=0;return;}
  111. }
  112. data[pos].pos=_p;
  113. data[pos].tm=tm;
  114. pos++;
  115. }
  116. int ReadSysex(const BYTE* src,int ml)
  117. {
  118. int r=1;
  119. while(r<ml)
  120. {
  121. r++;
  122. if (src[r]==0xF7) return r+1;
  123. }
  124. unsigned int d;
  125. r=1+DecodeDelta(src+1,&d);
  126. r+=d;
  127. return r;
  128. }
  129. unsigned int DecodeDelta(const BYTE* src,unsigned int* _d, unsigned int limit)
  130. {
  131. unsigned int l=0;
  132. unsigned int d=0;
  133. BYTE b;
  134. do
  135. {
  136. if (l >= limit)
  137. {
  138. *_d=0;
  139. return l;
  140. }
  141. b=src[l++];
  142. d=(d<<7)|(b&0x7F);
  143. } while(b&0x80);
  144. *_d=d;
  145. return l;
  146. }
  147. int EncodeDelta(BYTE* dst,int d)
  148. {
  149. if (d==0)
  150. {
  151. dst[0]=0;
  152. return 1;
  153. }
  154. else
  155. {
  156. int r=0;
  157. int n=1;
  158. unsigned int temp=d;
  159. while (temp >>= 7)
  160. {
  161. n++;
  162. }
  163. do {
  164. n--;
  165. BYTE b=(BYTE)((d>>(7*n))&0x7F);
  166. if (n) b|=0x80;
  167. dst[r++]=b;
  168. } while(n);
  169. return r;
  170. }
  171. }
  172. int CTempoMap::BuildTrack(grow_buf & out)
  173. {
  174. if (!pos) return 0;
  175. int start=out.get_size();
  176. //BYTE* trk=(BYTE*)malloc(8+4+pos*10);
  177. //if (!trk) return 0;
  178. out.write_dword(_rv('MTrk'));
  179. out.write_dword(0);//track size
  180. DWORD ct=0;
  181. int n;
  182. BYTE t_event[6]={0xFF,0x51,0x03,0,0,0};
  183. for(n=0;n<pos;n++)
  184. {
  185. DWORD t=data[n].pos;
  186. gb_write_delta(out,t-ct);
  187. ct=t;
  188. t=data[n].tm;
  189. t_event[3]=(BYTE)(t>>16);
  190. t_event[4]=(BYTE)(t>>8);
  191. t_event[5]=(BYTE)(t);
  192. out.write(t_event,6);
  193. }
  194. out.write_dword(0x002FFF00);
  195. out.write_dword_ptr(rev32(out.get_size()-(start+8)),start+4);
  196. return 1;
  197. }
  198. //sysex map management
  199. void CSysexMap::AddEvent(const BYTE* e,DWORD s,DWORD t)
  200. {
  201. if (!data || !events) return;
  202. DWORD np=pos+1;
  203. if (np>=e_size)
  204. {
  205. do {
  206. e_size<<=1;
  207. } while(np>=e_size);
  208. events=(SYSEX_ENTRY*)realloc(events,e_size*sizeof(SYSEX_ENTRY));
  209. if (!events) return;
  210. }
  211. DWORD nd=d_pos+s;
  212. if (nd>=d_size)
  213. {
  214. do {
  215. d_size<<=1;
  216. } while(nd>=d_size);
  217. data=(BYTE*)realloc(data,d_size);
  218. if (!data) return;
  219. }
  220. data[d_pos]=0xF0;
  221. unsigned int x;
  222. unsigned int sp=DecodeDelta(e+1,&x);
  223. if (sp >= s)
  224. return;
  225. memcpy(data+d_pos+1,e+1+sp,s-1-sp);
  226. events[pos].pos=t;
  227. events[pos].ofs=d_pos;
  228. events[pos].len=s-sp;
  229. d_pos=nd-sp;
  230. pos++;
  231. }
  232. CSysexMap* smap_create()
  233. {
  234. CSysexMap* s=new CSysexMap;
  235. if (s)
  236. {
  237. s->e_size=0x10;
  238. s->d_size=0x40;
  239. s->events=(SYSEX_ENTRY*)malloc(sizeof(SYSEX_ENTRY)*s->e_size);
  240. s->data=(BYTE*)malloc(s->d_size);
  241. s->d_pos=s->pos=0;
  242. }
  243. return s;
  244. }
  245. CSysexMap::~CSysexMap()
  246. {
  247. if (data) free(data);
  248. if (events) free(events);
  249. }
  250. BYTE d_GMReset[6]={0xF0,0x7E,0x7F,0x09,0x01,0xF7};
  251. BYTE d_XGReset[9]={0xf0,0x43,0x10,0x4c,0x00,0x00,0x7e,0x00,0xf7};
  252. BYTE d_GSReset[11]={0xF0,0x41,0x10,0x42,0x12,0x40,0x00,0x7F,0x00,0x41,0xF7};
  253. CSysexMap* CSysexMap::Translate(MIDI_file * mf)
  254. {
  255. CTempoMap* tmap=mf->tmap;
  256. if (!events || !data || !tmap) return 0;
  257. CSysexMap* nm=smap_create();
  258. if (!nm) return 0;
  259. nm->d_size=d_size;
  260. nm->d_pos=d_pos;
  261. nm->data=(BYTE*)realloc(nm->data,nm->d_size);
  262. if (!nm->data) {delete nm;return 0;}
  263. memcpy(nm->data,data,d_pos);
  264. nm->e_size=e_size;
  265. nm->pos=pos;
  266. nm->events=(SYSEX_ENTRY*)realloc(nm->events,sizeof(SYSEX_ENTRY)*nm->e_size);
  267. if (!nm->events) {delete nm;return 0;}
  268. int pos_ms=0;
  269. int n=0;
  270. int cur_temp=0;
  271. int ntm=tmap->pos,t_pos=0;
  272. int p_t=0;
  273. int dtx = rev16(*(WORD*)(mf->data+12))*1000;
  274. int pos_tx=0;
  275. while(n<pos)
  276. {
  277. pos_tx=events[n].pos;
  278. int d=pos_tx-p_t;
  279. p_t=pos_tx;
  280. while(t_pos<ntm && pos_tx+d>=tmap->data[t_pos].pos)
  281. {
  282. DWORD d1=tmap->data[t_pos].pos-pos_tx;
  283. pos_ms+=MulDiv(cur_temp,d1<<8,dtx);
  284. cur_temp=tmap->data[t_pos].tm;
  285. t_pos++;
  286. pos_tx+=d1;
  287. d-=d1;
  288. }
  289. pos_ms+=MulDiv(cur_temp,d<<8,dtx);
  290. pos_tx+=d;
  291. nm->events[n].pos=pos_ms>>8;
  292. nm->events[n].ofs=events[n].ofs;
  293. nm->events[n].len=events[n].len;
  294. n++;
  295. }
  296. return nm;
  297. }
  298. int CSysexMap::BuildTrack(grow_buf & out)
  299. {
  300. if (!pos) return 0;
  301. int start=out.get_size();
  302. out.write_dword(_rv('MTrk'));
  303. out.write_dword(0);
  304. int ct=0;
  305. int n;
  306. for(n=0;n<pos;n++)
  307. {
  308. DWORD t=events[n].pos;
  309. gb_write_delta(out,t-ct);
  310. ct=t;
  311. out.write_byte(0xF0);
  312. gb_write_delta(out,events[n].len-1);
  313. out.write(data+events[n].ofs+1,events[n].len-1);
  314. }
  315. out.write_dword(0x002FFF00);
  316. out.write_dword_ptr(rev32(out.get_size()-(start+8)),start+4);
  317. return 1;
  318. }
  319. const char* CSysexMap::GetType()
  320. {
  321. int ret=0;
  322. int n;
  323. for(n=0;n<pos;n++)
  324. {
  325. ret=data[events[n].ofs+1];
  326. if (ret!=0x7E) break;
  327. }
  328. switch(ret)
  329. {
  330. case 0x7E:
  331. return "GM";
  332. case 0x43:
  333. return "XG";
  334. case 0x42:
  335. return "X5";
  336. case 0x41:
  337. return "GS";
  338. }
  339. return 0;
  340. }
  341. void CSysexMap::CleanUp()
  342. {
  343. if (!pos) return;
  344. int n,m;
  345. for(n=0;n<pos-1;n++)
  346. {
  347. for(m=n+1;m<pos;m++)
  348. {
  349. if (events[n].pos>events[m].pos)
  350. {
  351. SYSEX_ENTRY t=events[n];
  352. events[n]=events[m];
  353. events[m]=t;
  354. }
  355. }
  356. }
  357. }
  358. char* BuildFilterString(UINT res_id, char* ext, int* len)
  359. {
  360. static char filterStr[256];
  361. char *f = filterStr;
  362. ZeroMemory(filterStr,256);
  363. *len = 0;
  364. WASABI_API_LNGSTRING_BUF(res_id,filterStr,256);
  365. f += (*len = lstrlenA(filterStr) + 1);
  366. lstrcatA(f,"*.");
  367. f += 2;
  368. lstrcatA(f,ext);
  369. *(f + lstrlenA(ext)+1) = 0;
  370. *len += lstrlenA(ext)+3;
  371. return filterStr;
  372. }
  373. BOOL DoOpenFile(HWND w,char* fn,UINT res_id, char* ext,BOOL save)
  374. {
  375. int len = 0;
  376. OPENFILENAMEA ofn = {sizeof(ofn),0};
  377. ofn.hwndOwner=w;
  378. ofn.lpstrFilter=BuildFilterString(res_id,ext,&len);
  379. ofn.lpstrFile=fn;
  380. ofn.nMaxFile=MAX_PATH;
  381. ofn.lpstrDefExt=ext;
  382. if (save)
  383. {
  384. ofn.Flags=OFN_OVERWRITEPROMPT|OFN_PATHMUSTEXIST|OFN_HIDEREADONLY;
  385. return GetSaveFileNameA(&ofn);
  386. }
  387. else
  388. {
  389. ofn.Flags=OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST|OFN_HIDEREADONLY;
  390. return GetOpenFileNameA(&ofn);
  391. }
  392. }
  393. BOOL DoSaveFile(HWND w, char* fn, char* filt, char* ext)
  394. {
  395. OPENFILENAMEA ofn;
  396. ZeroMemory(&ofn,sizeof(ofn));
  397. ofn.lStructSize=sizeof(ofn);
  398. ofn.hwndOwner=w;
  399. ofn.lpstrFilter=filt;
  400. ofn.lpstrFile=fn;
  401. ofn.nMaxFile=MAX_PATH;
  402. ofn.lpstrDefExt=ext;
  403. ofn.Flags=OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST|OFN_HIDEREADONLY;
  404. return GetOpenFileNameA(&ofn);
  405. }
  406. typedef void (*SYSEXFUNC)(void*,BYTE*,UINT);
  407. #define rsysex(X) f(i,X,sizeof(X))
  408. #define _sysex(X,Y) f(i,X,Y)
  409. bool need_sysex_start()
  410. {
  411. return cfg_hardware_reset>0
  412. || cfg_sysex_table.num_entries()>0
  413. ;
  414. }
  415. void sysex_startup(SYSEXFUNC f,void* i)
  416. {
  417. if (cfg_hardware_reset>0)
  418. {
  419. switch(cfg_hardware_reset)
  420. {
  421. case 1:rsysex(d_GMReset);break;
  422. case 2:rsysex(d_GSReset);break;
  423. case 3:rsysex(d_XGReset);break;
  424. }
  425. MIDI_callback::Idle(200);
  426. }
  427. if (cfg_sysex_table.num_entries()>0)
  428. {
  429. int idx=0;
  430. BYTE * data;
  431. int size,time;
  432. while(cfg_sysex_table.get_entry(idx++,&data,&size,&time))
  433. {
  434. _sysex(data,size);
  435. MIDI_callback::Idle(time);
  436. }
  437. }
  438. }
  439. MIDI_EVENT* do_table(MIDI_file * mf,UINT prec,UINT * size,UINT* _lstart,DWORD cflags)
  440. {
  441. BYTE * data_ptr = 0;
  442. int data_size = 0;
  443. if (!DoCleanUp(mf,CLEAN_1TRACK|CLEAN_NOSYSEX|CLEAN_NOTEMPO|cflags,(void**)&data_ptr,&data_size)) return 0;
  444. if (data_size<=0x0e) {free(data_ptr);return 0;}
  445. UINT ts;
  446. BYTE* track;
  447. UINT ntm;
  448. track=data_ptr+8+6+8;
  449. ts=rev32(*(DWORD*)(track-4));
  450. CTempoMap* tmap=mf->tmap;
  451. UINT n=0;
  452. UINT pt=0;
  453. ntm=tmap->pos;
  454. CSysexMap* smap;
  455. if (!cfg_nosysex && mf->smap && mf->smap->pos)
  456. {
  457. smap=mf->smap;
  458. }
  459. else smap=0;
  460. n=0;
  461. DWORD pos=0;
  462. DWORD pos_ms=0;
  463. DWORD t_pos=0;
  464. DWORD cur_temp=0;
  465. UINT dtx=(UINT)rev16(*(WORD*)(data_ptr+8+4))*1000/prec;
  466. grow_buf boo;
  467. int ns=0;
  468. UINT track_pos=0,smap_pos=0;
  469. UINT loop_start=-1;
  470. {
  471. unsigned int _d;
  472. n+=DecodeDelta(track+n,&_d);
  473. track_pos+=_d;
  474. }
  475. if (smap)
  476. {
  477. smap_pos=smap->events[0].pos;
  478. }
  479. else smap_pos=-1;
  480. while(1)
  481. {
  482. DWORD ev=0;
  483. DWORD d=0;
  484. {
  485. if (n >= (data_size-26))
  486. break;
  487. if (track_pos<smap_pos)
  488. {
  489. d=track_pos-pos;
  490. ev=(*(DWORD*)(track+n))&0xFFFFFF;
  491. if ((ev&0xF0)==0xF0)
  492. {
  493. track_pos=-1;
  494. continue;
  495. }
  496. if ((ev&0xF0)==0xC0 || (ev&0xF0)==0xD0)
  497. {
  498. ev&=0xFFFF;n+=2;
  499. }
  500. else
  501. {
  502. n+=3;
  503. }
  504. if ((ev&0xFF00F0)==0x90)
  505. {
  506. ev=(ev&0xFF0F)|0x7F0080;
  507. }
  508. unsigned int _d;
  509. n+=DecodeDelta(track+n,&_d);
  510. track_pos+=_d;
  511. if (n >= (data_size-26))
  512. break;
  513. }
  514. else if (smap_pos!=-1)
  515. {
  516. d=smap_pos-pos;
  517. ev=0x80000000|ns;
  518. ns++;
  519. if (ns==smap->pos)
  520. smap_pos=-1;
  521. else
  522. smap_pos=smap->events[ns].pos;
  523. }
  524. }
  525. if (!ev) break;
  526. while(t_pos<ntm && pos+d>=(UINT)tmap->data[t_pos].pos)
  527. {
  528. DWORD d1=tmap->data[t_pos].pos-pos;
  529. if (loop_start==-1 && (UINT)mf->loopstart_t<=pos+d1) loop_start=pos_ms+MulDiv(cur_temp,pos+d1-mf->loopstart_t,dtx);
  530. pos_ms+=MulDiv(cur_temp,d1,dtx);
  531. cur_temp=tmap->data[t_pos].tm;
  532. t_pos++;
  533. pos+=d1;
  534. d-=d1;
  535. }
  536. if (loop_start==-1 && (UINT)mf->loopstart_t<=pos+d) loop_start=pos_ms+MulDiv(cur_temp,d,dtx);
  537. pos_ms+=MulDiv(cur_temp,d,dtx);
  538. pos+=d;
  539. {
  540. MIDI_EVENT me={pos_ms,ev};
  541. boo.write(&me,sizeof(me));
  542. }
  543. }
  544. free(data_ptr);
  545. UINT sz=boo.get_size();
  546. MIDI_EVENT* ret=(MIDI_EVENT*)boo.finish();
  547. if (ret)
  548. {
  549. *size=sz>>3;//sz/sizeof(MIDI_EVENT);
  550. if (cfg_loop_type==2 && loop_start==-1) loop_start=0;
  551. else if (cfg_loop_type==0) loop_start=-1;
  552. if (_lstart) *_lstart=loop_start;
  553. }
  554. return ret;
  555. }
  556. void gb_write_delta(grow_buf & gb,DWORD d)
  557. {
  558. BYTE tmp[8] = {0};
  559. gb.write(tmp,EncodeDelta(tmp,d));
  560. }
  561. void do_messages(HWND w,bool* b)
  562. {
  563. MSG msg;
  564. while(b && *b)
  565. {
  566. BOOL b=GetMessage(&msg,w,0,0);
  567. if (b==-1 || !b) break;
  568. DispatchMessage(&msg);
  569. }
  570. }
  571. static wchar_t cb_class[]=TEXT("CallbackWndClass0");
  572. ATOM do_callback_class(WNDPROC p)
  573. {
  574. cb_class[sizeof(cb_class)-2]++;
  575. WNDCLASS wc=
  576. {
  577. 0,p,0,4,MIDI_callback::GetInstance(),0,0,0,0,cb_class
  578. };
  579. return RegisterClassW(&wc);
  580. }
  581. HWND create_callback_wnd(ATOM cl,void* p)
  582. {
  583. HWND w=CreateWindowA((char*)cl,0,0,0,0,0,0,MIDI_callback::GetMainWindow(),0,MIDI_callback::GetInstance(),0);
  584. if (w) SetWindowLong(w,0,(long)p);
  585. return w;
  586. }
  587. CTempoMap* tmap_merge(CTempoMap* m1,CTempoMap* m2)
  588. {
  589. int p1=0,p2=0;
  590. CTempoMap * ret=0;
  591. if (m1 && m2 && m1->data && m2->data)
  592. {
  593. ret=tmap_create();
  594. if (ret)
  595. {
  596. while(p1<m1->pos && p2<m2->pos)
  597. {
  598. if (m1->data[p1].pos<=m2->data[p2].pos)
  599. {
  600. ret->AddEntry(m1->data[p1].pos,m1->data[p1].tm);
  601. p1++;
  602. }
  603. else
  604. {
  605. ret->AddEntry(m2->data[p2].pos,m2->data[p2].tm);
  606. p2++;
  607. }
  608. }
  609. while(p1<m1->pos)
  610. {
  611. ret->AddEntry(m1->data[p1].pos,m1->data[p1].tm);
  612. p1++;
  613. }
  614. while(p2<m2->pos)
  615. {
  616. ret->AddEntry(m2->data[p2].pos,m2->data[p2].tm);
  617. p2++;
  618. }
  619. }
  620. }
  621. if (m1) delete m1;
  622. if (m2) delete m2;
  623. return ret;
  624. }
  625. KAR_ENTRY * kmap_create(MIDI_file* mf,UINT prec,UINT * num,char** text)
  626. {
  627. if (!mf->kar_track) return 0;
  628. grow_buf b_data,b_map;
  629. KAR_ENTRY te;
  630. BYTE *track=(BYTE*)mf->data+mf->kar_track+8;
  631. BYTE *track_end = track+rev32(*(DWORD*)(mf->data+mf->kar_track+4));
  632. int time=0;
  633. int ptr=0;
  634. BYTE lc=0;
  635. while(track<track_end)
  636. {
  637. unsigned int d;
  638. track+=DecodeDelta(track,&d);
  639. time+=d;
  640. if (*track==0xFF) //meta
  641. {
  642. BYTE type=track[1];
  643. track+=2;
  644. track+=DecodeDelta(track,&d);
  645. char * ptr=(char*)track;
  646. track+=d;
  647. if ((type==0x5 || type==0x1) && d && *ptr!='@') //lyrics
  648. {
  649. te.time=time;
  650. te.foo=1;
  651. unsigned int n;
  652. te.start=b_data.get_size();
  653. for(n=0;n<d;n++)
  654. {
  655. switch(ptr[n])
  656. {
  657. // case '@':
  658. case '\\':
  659. case '/':
  660. case 0x0D:
  661. b_data.write("\x0d\x0a",2);
  662. break;
  663. case 0x0A:
  664. break;
  665. default:
  666. te.foo=0;
  667. b_data.write_byte(ptr[n]);
  668. break;
  669. }
  670. }
  671. te.end=b_data.get_size();
  672. if (te.start<te.end) b_map.write(&te,sizeof(te));
  673. }
  674. }
  675. else if (*track==0xF0)
  676. {
  677. track++;
  678. track+=DecodeDelta(track,&d);
  679. track+=d;
  680. }
  681. else if ((*track&0xF0)==0xF0)
  682. {
  683. track++;//hack
  684. }
  685. else
  686. {
  687. if (*track&0x80) lc=*(track++)&0xF0;
  688. if (lc==0 || lc==0xC0 || lc==0xD0) track++;
  689. else track+=2;
  690. }
  691. }
  692. int map_siz = b_map.get_size();
  693. KAR_ENTRY * map=(KAR_ENTRY*)b_map.finish();
  694. map_siz/=sizeof(KAR_ENTRY);
  695. if (num) *num=map_siz;
  696. if (text)
  697. {
  698. b_data.write_byte(0);
  699. *text=(char*)b_data.finish();
  700. }
  701. else b_data.reset();
  702. if (map)
  703. {
  704. int n;
  705. time=0;
  706. CTempoMap* tmap=mf->tmap;
  707. int pos_ms=0;
  708. int t_pos=0;
  709. int cur_temp=0;
  710. int dtx=(UINT)rev16(*(WORD*)(mf->data+8+4))*1000/prec;
  711. for(n=0;n<map_siz;n++)
  712. {
  713. int d=0;
  714. d=map[n].time-time;
  715. while(t_pos<tmap->pos && time+d>=tmap->data[t_pos].pos)
  716. {
  717. DWORD d1=tmap->data[t_pos].pos-time;
  718. pos_ms+=MulDiv(cur_temp,d1,dtx);
  719. cur_temp=tmap->data[t_pos].tm;
  720. t_pos++;
  721. time+=d1;
  722. d-=d1;
  723. }
  724. pos_ms+=MulDiv(cur_temp,d,dtx);
  725. time+=d;
  726. map[n].time=pos_ms;
  727. }
  728. }
  729. return map;
  730. }
  731. int sysex_table::num_entries() const
  732. {
  733. int num=0;
  734. entry * ptr=entries;
  735. while(ptr) {ptr=ptr->next;num++;}
  736. return num;
  737. }
  738. int sysex_table::get_entry(int idx,BYTE ** p_data,int * p_size,int * p_time) const
  739. {
  740. entry * ptr=entries;
  741. while(ptr && idx>0) {ptr=ptr->next;idx--;}
  742. if (!ptr) return 0;
  743. if (p_data) *p_data = ptr->data;
  744. if (p_size) *p_size = ptr->size;
  745. if (p_time) *p_time = ptr->time;
  746. return 1;
  747. }
  748. void sysex_table::insert_entry(int idx,BYTE * data,int size,int time)
  749. {
  750. entry ** ptr = &entries;
  751. while(idx>0 && *ptr)
  752. {
  753. ptr = &(*ptr)->next;
  754. idx--;
  755. }
  756. entry * insert = new entry;
  757. insert->data = (BYTE*)malloc(size);
  758. memcpy(insert->data,data,size);
  759. insert->size = size;
  760. insert->time = time;
  761. insert->next = *ptr;
  762. *ptr = insert;
  763. }
  764. int sysex_table::remove_entry(int idx)
  765. {
  766. entry ** ptr = &entries;
  767. while(idx>0 && *ptr)
  768. {
  769. ptr = &(*ptr)->next;
  770. idx--;
  771. }
  772. if (!*ptr) return 0;
  773. entry * remove = *ptr;
  774. *ptr=remove->next;
  775. free(remove->data);
  776. delete remove;
  777. return 1;
  778. }
  779. int sysex_table::file_write(const char* file) const
  780. {
  781. HANDLE f=CreateFileA(file,GENERIC_WRITE,0,0,CREATE_ALWAYS,0,0);
  782. if (f==INVALID_HANDLE_VALUE) return 0;
  783. int size;
  784. void * ptr = memblock_write(&size);
  785. DWORD bw = 0;
  786. WriteFile(f,ptr,size,&bw,0);
  787. free(ptr);
  788. CloseHandle(f);
  789. return 1;
  790. }
  791. void * sysex_table::memblock_write(int * size) const
  792. {
  793. grow_buf wb;
  794. entry * ptr;
  795. //MAGIC:DWORD , NUM: DWORD,DATA_SIZE:DWORD, offsets, sleep,data
  796. DWORD temp;
  797. temp=MHP_MAGIC;
  798. wb.write(&temp,4);
  799. temp=num_entries();
  800. wb.write(&temp,4);
  801. temp=0;
  802. for(ptr=entries;ptr;ptr=ptr->next) temp+=ptr->size;
  803. wb.write(&temp,4);
  804. temp=0;
  805. for(ptr=entries;ptr;ptr=ptr->next)
  806. {
  807. wb.write(&temp,4);
  808. temp+=ptr->size;
  809. }
  810. for(ptr=entries;ptr;ptr=ptr->next)
  811. {
  812. temp = ptr->time;
  813. wb.write(&temp,4);
  814. }
  815. for(ptr=entries;ptr;ptr=ptr->next)
  816. {
  817. wb.write(ptr->data,ptr->size);
  818. }
  819. if (size) *size = wb.get_size();
  820. return wb.finish();
  821. }
  822. int sysex_table::memblock_read(const void * block,int size)
  823. {
  824. entry * ptr;
  825. const BYTE * src = (const BYTE*)block;
  826. DWORD temp,total_size,total_num;
  827. if (*(DWORD*)src!=MHP_MAGIC) return 0;
  828. src+=4;
  829. temp=total_num=*(DWORD*)src;
  830. src+=4;
  831. if (total_num>0xFFFF) return 0;
  832. reset();
  833. while(temp>0)
  834. {
  835. ptr=new entry;
  836. ptr->next=entries;
  837. entries = ptr;
  838. temp--;
  839. }
  840. total_size=*(DWORD*)src;
  841. UINT n;
  842. for(n=0,ptr=entries;ptr;ptr=ptr->next,n++)
  843. {
  844. //offset : 12 + 4 * n;
  845. //time : 12 + 4 * total_num + 4 * n;
  846. //data : 12 + 8 * total_num + offset
  847. DWORD offset,time,offset2;
  848. src = (const BYTE*)block + 12 + 4*n;
  849. offset=*(DWORD*)src;
  850. if (n!=total_num-1) offset2=*(DWORD*)(src+4);
  851. else offset2=total_size;
  852. ptr->size = offset2-offset;
  853. src = (const BYTE*)block + 12 + 4*total_num + 4*n;
  854. time = *(DWORD*)src;
  855. ptr->data = (BYTE*)malloc(offset2);
  856. src = (const BYTE*)block + 12 + 8*total_num + offset;
  857. memcpy(ptr->data,src,ptr->size);
  858. ptr->time = time;
  859. }
  860. return 1;
  861. }
  862. int sysex_table::file_read(const char* file)
  863. {
  864. HANDLE f=CreateFileA(file,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,0,0);
  865. if (f==INVALID_HANDLE_VALUE) return 0;
  866. int size = GetFileSize(f,0);
  867. void * temp = malloc(size);
  868. DWORD br = 0;
  869. ReadFile(f,temp,size,&br,0);
  870. CloseHandle(f);
  871. int rv = memblock_read(temp,size);
  872. free(temp);
  873. return rv;
  874. }
  875. int sysex_table::print_preview(int idx,char * out) const
  876. {
  877. BYTE* data;
  878. int size,time;
  879. if (!get_entry(idx,&data,&size,&time)) return 0;
  880. int size2=size;
  881. if (size2>10) size2=10;
  882. wsprintfA(out,WASABI_API_LNGSTRING(STRING_MS_FMT),time);
  883. while(out && *out) out++;
  884. int n;
  885. for(n=0;n<size2;n++)
  886. {
  887. wsprintfA(out," %02X",data[n]);
  888. out+=3;
  889. }
  890. if (size!=size2)
  891. {
  892. strcpy(out,"...");
  893. }
  894. return 1;
  895. }
  896. void sysex_table::print_edit(int idx,HWND wnd) const
  897. {
  898. BYTE* data;
  899. int size,time;
  900. if (!get_entry(idx,&data,&size,&time)) {SetWindowTextA(wnd,"");return;}
  901. if (size<=2) {SetWindowTextA(wnd,"");return;}
  902. char *temp = (char*)malloc(3*size);
  903. char *ptr = temp;
  904. int n;
  905. for(n=1;n<size-1;n++)
  906. {
  907. wsprintfA(ptr,"%02X ",data[n]);
  908. ptr+=3;
  909. }
  910. ptr[-1]=0;
  911. SetWindowTextA(wnd,temp);
  912. free(temp);
  913. }
  914. void sysex_table::copy(const sysex_table & src)
  915. {
  916. reset();
  917. int idx=0;
  918. BYTE * data;
  919. int size,time;
  920. while(src.get_entry(idx++,&data,&size,&time))//ASS SLOW
  921. insert_entry(idx,data,size,time);
  922. }
  923. //special sysex table cfg_var hack
  924. class cfg_var_sysex : private cfg_var
  925. {
  926. private:
  927. sysex_table * tab;
  928. virtual void read(HKEY hk)
  929. {
  930. int size=reg_get_struct_size(hk);
  931. if (size>0)
  932. {
  933. void * temp = malloc(size);
  934. if (temp)
  935. {
  936. reg_read_struct(hk,temp,size);
  937. tab->memblock_read(temp,size);
  938. free(temp);
  939. }
  940. }
  941. }
  942. virtual void write(HKEY hk)
  943. {
  944. void * data;
  945. int size;
  946. data = tab->memblock_write(&size);
  947. if (data) reg_write_struct(hk,data,size);
  948. }
  949. virtual void reset() {tab->reset();}
  950. public:
  951. cfg_var_sysex(const char * name,sysex_table * p_tab) : cfg_var(name) {tab=p_tab;}
  952. };
  953. static cfg_var_sysex thevar("sysex_table",&cfg_sysex_table);