wa2.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820
  1. #include "main.h"
  2. #include "resource.h"
  3. #include <shlwapi.h>
  4. #include <api/service/waServiceFactory.h>
  5. #include "../winamp/wa_ipc.h"
  6. #include "../Agave/language/api_language.h"
  7. #include "CompressionUtility.h"
  8. #include "minizip/unzip.h"
  9. static bool paused;
  10. static int volume=255;
  11. static int pan=0;
  12. static string cur_file;
  13. static HANDLE thread;
  14. static HINSTANCE hRFdll;
  15. static reader_source * pRF;
  16. // wasabi based services for localisation support
  17. api_language *WASABI_API_LNG = 0;
  18. HINSTANCE WASABI_API_LNG_HINST = 0, WASABI_API_ORIG_HINST = 0;
  19. #define IPC_GETHTTPGETTER 240
  20. typedef int (*t_getf)(HWND hwnd, char *url, char *file, char *dlgtitle);
  21. static WReader * get_reader(const char * fn);//wa2 hack
  22. static int reader_process_file(WReader * r,const char * fn,void * &out_data, size_t &out_size)
  23. {
  24. void * data=0;
  25. int size=0;
  26. char ks=0;
  27. if (r->Open((char*)fn,&ks))
  28. return 0;
  29. size = r->GetLength();
  30. if (size==-1 || size<0x20)
  31. return 0;
  32. data=malloc(size);//scan funcs assume that theres at least 256 data
  33. if (!data)
  34. return 0;
  35. if (r->Read((char*)data,size,&ks)!=size)
  36. {
  37. free(data);
  38. return 0;
  39. }
  40. void* pvOut;
  41. size_t nSizeOut = 0;
  42. // GZIP
  43. if (((*(DWORD*)data) & 0xFFFFFF) == 0x088b1f)
  44. {
  45. if (CompressionUtility::DecompressGZip(data, size, &pvOut, nSizeOut) >= 0)
  46. {
  47. out_data = pvOut;
  48. out_size = nSizeOut;
  49. return 1;
  50. }
  51. else
  52. {
  53. return 0;
  54. }
  55. }
  56. // PKZIP
  57. else if (*(DWORD*)data == 0x04034B50)
  58. {
  59. if (CompressionUtility::DecompressPKZip(fn, &pvOut, nSizeOut) >= 0)
  60. {
  61. out_data = pvOut;
  62. out_size = nSizeOut;
  63. return 1;
  64. }
  65. else
  66. {
  67. return 0;
  68. }
  69. }
  70. out_size = size;
  71. out_data = data;
  72. return 1;
  73. }
  74. MIDI_file * wa2_open_file(const char * url)
  75. {
  76. WReader * r=get_reader(url);
  77. if (!r) return 0;
  78. void * data=0;
  79. size_t size=0;
  80. MIDI_file* mf=0;
  81. if (reader_process_file(r,url,data,size))
  82. {
  83. mf=MIDI_file::Create(url,data,size);
  84. free(data);
  85. }
  86. delete r;
  87. return mf;
  88. }
  89. static void build_fmtstring();
  90. static cfg_int cfg_mod_output("dev_output",1);
  91. static void wa2_onCfgUpdate()
  92. {
  93. MIDI_device * dev = MIDI_driver::find_device(cfg_driver,cfg_device);
  94. if (!dev)
  95. {
  96. dev = MIDI_driver::find_device_default();
  97. }
  98. //hack for wa2input.wac in wa3
  99. mod.UsesOutputPlug=(dev->has_output() || (cfg_smp && cfg_sampout)) ? 1 : 0x8001;
  100. cfg_mod_output=mod.UsesOutputPlug;
  101. build_fmtstring();
  102. }
  103. static char fmts_string[1024];
  104. #define NSEEK(a) {while(!(cfg_ext_mask&(1<<a)) && a<n_exts) a++;}
  105. static void build_fmtstring()
  106. {
  107. UINT n_exts = MIDI_core::FileTypes_GetNum();
  108. if (!cfg_ext_mask)
  109. {
  110. fmts_string[1]=fmts_string[0]=0;
  111. return;
  112. }
  113. UINT n=0;
  114. NSEEK(n);
  115. const char* d=MIDI_core::FileTypes_GetDescription(n);
  116. char* o=fmts_string;
  117. while(1)
  118. {
  119. UINT f=n;
  120. while(n<n_exts && d==MIDI_core::FileTypes_GetDescription(n))
  121. {
  122. const char * e=MIDI_core::FileTypes_GetExtension(n);
  123. while(e && *e) *(o++)=*(e++);
  124. n++;
  125. NSEEK(n);
  126. *(o++)=';';
  127. }
  128. o[-1]=0;
  129. while(d && *d) *(o++)=*(d++);
  130. *(o++)=' ';
  131. *(o++)='(';
  132. while(f<n)
  133. {
  134. const char * e=MIDI_core::FileTypes_GetExtension(f);
  135. while(e && *e) *(o++)=*(e++);
  136. f++;
  137. NSEEK(f);
  138. *(o++)=',';
  139. }
  140. o[-1]=')';
  141. *(o++)=0;
  142. if (n>=n_exts) break;
  143. d=MIDI_core::FileTypes_GetDescription(n);
  144. }
  145. if (cfg_extra_exts.get_string().length()>0)
  146. {
  147. d=cfg_extra_exts;
  148. while(d && *d) *(o++)=*(d++);
  149. *(o++)=0;
  150. d=WASABI_API_LNGSTRING(STRING_FILES_OTHER);
  151. while(d && *d) *(o++)=*(d++);
  152. d=cfg_extra_exts;
  153. while(d && *d)
  154. {
  155. if (*d==';') *o=',';
  156. else *o=*d;
  157. o++;
  158. d++;
  159. }
  160. *(o++)=')';
  161. *(o++)=0;
  162. }
  163. *(o++)=0;
  164. }
  165. #undef NSEEK
  166. static void Config(HWND p)
  167. {
  168. if (MIDI_core::Config(p))
  169. {
  170. MIDI_core::WriteConfig();
  171. wa2_onCfgUpdate();
  172. }
  173. }
  174. void About(HWND);
  175. class CMemReader : public WReader
  176. {
  177. public:
  178. BYTE* mem;
  179. UINT sz;
  180. UINT pos;
  181. int Open(char *url, char *killswitch);
  182. int Read(char *buffer, int length, char* killswitch) {if (!mem) return 0;if (length+pos>sz) length=sz-pos;memcpy(buffer,mem+pos,length);pos+=length;return length;}
  183. int GetLength(void) {return sz;}
  184. int CanSeek(void) {return 1;};
  185. int Seek(int position, char*killswitch) {pos=position;return 0;};
  186. CMemReader() {mem=0;sz=0;pos=0;}
  187. ~CMemReader() {if (mem) free(mem);}
  188. };
  189. static int Download(char* url,UINT* f_size,BYTE** m_buf)
  190. {
  191. typedef int (*t_getf)(HWND hwnd, char *url, char *file, char *dlgtitle);
  192. t_getf getf;
  193. int t=SendMessage(mod.hMainWindow,WM_USER,0,IPC_GETHTTPGETTER);
  194. if (!t || t==1)
  195. {
  196. #ifndef WINAMPX
  197. MessageBoxA(mod.hMainWindow,WASABI_API_LNGSTRING(STRING_URL_ERROR),ERROR,MB_ICONERROR);
  198. #endif
  199. return 0;
  200. }
  201. else
  202. {
  203. int rv=0;
  204. char tmp[MAX_PATH] = {0};
  205. get_temp_file(tmp);
  206. HANDLE f;
  207. DWORD br = 0,s = 0;
  208. void* b;
  209. getf=(t_getf)t;
  210. if (getf(mod.hMainWindow,url,tmp,WASABI_API_LNGSTRING(STRING_RETRIEVING_FILE))) goto fail;
  211. f=CreateFileA(tmp,GENERIC_READ,0,0,OPEN_EXISTING,0,0);
  212. if (f==INVALID_HANDLE_VALUE) goto fail;
  213. br=0;
  214. s=GetFileSize(f,0);
  215. if (!s) goto fail;
  216. b=malloc(s);
  217. if (!b) goto fail;
  218. ReadFile(f,b,s,&br,0);
  219. rv=1;
  220. *f_size=br;
  221. *m_buf=(BYTE*)b;
  222. fail:
  223. CloseHandle(f);
  224. DeleteFileA(tmp);
  225. return rv;
  226. }
  227. }
  228. int CMemReader::Open(char* url,char*)
  229. {
  230. sz=pos=0;
  231. if (mem) {free(mem);mem=0;}
  232. HANDLE f=CreateFileA(url,GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE,0,OPEN_EXISTING,0,0);
  233. if (f!=INVALID_HANDLE_VALUE)
  234. {
  235. sz=GetFileSize(f,0);
  236. mem=(BYTE*)malloc(sz);
  237. if (!mem) {CloseHandle(f);return 1;}
  238. ReadFile(f,mem,sz,(DWORD*)&sz,0);
  239. CloseHandle(f);
  240. return 0;
  241. }
  242. return !Download(url,&sz,&mem);
  243. }
  244. class CFileReader : public WReader
  245. {
  246. public:
  247. HANDLE f;
  248. CFileReader() {f=0;};
  249. ~CFileReader() {if (f) CloseHandle(f);}
  250. int Open(char *url, char*killswitch) {f=CreateFileA(url,GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE,0,OPEN_EXISTING,0,0);return f==INVALID_HANDLE_VALUE;}
  251. int Read(char *buffer, int length, char*killswitch) {DWORD br=0;ReadFile(f,buffer,length,&br,0);return br;}
  252. int GetLength(void) {return GetFileSize(f,0);}
  253. int CanSeek(void) {return 1;};
  254. int Seek(int position, char*killswitch) {SetFilePointer(f,position,0,FILE_BEGIN);return 0;}
  255. };
  256. static WReader *get_reader(const char* url)
  257. {
  258. if (!_strnicmp(url,"file://",7)) url+=7;
  259. WReader* ret=0;
  260. if (pRF && pRF->ismine((char*)url)) ret=pRF->create();
  261. if (ret)
  262. {
  263. ret->m_player=0;
  264. return ret;
  265. }
  266. if (_strnicmp(url,"http://",7)==0 || _strnicmp(url,"ftp://",6)==0 || _strnicmp(url,"https://",8)==0) return new CMemReader;
  267. return new CFileReader();
  268. }
  269. int Init()
  270. {
  271. if (!IsWindow(mod.hMainWindow))
  272. return IN_INIT_FAILURE;
  273. // loader so that we can get the localisation service api for use
  274. waServiceFactory *sf = mod.service->service_getServiceByGuid(languageApiGUID);
  275. if (sf) WASABI_API_LNG = reinterpret_cast<api_language*>(sf->getInterface());
  276. // need to have this initialised before we try to do anything with localisation features
  277. WASABI_API_START_LANG(mod.hDllInstance,InMidiLangGUID);
  278. static wchar_t szDescription[256];
  279. swprintf(szDescription,256,WASABI_API_LNGSTRINGW(IDS_NULLSOFT_MIDI_PLAYER),VER);
  280. mod.description = (char*)szDescription;
  281. MIDI_core::GlobalInit();
  282. mod.UsesOutputPlug=cfg_mod_output;
  283. build_fmtstring();
  284. return IN_INIT_SUCCESS;
  285. }
  286. void Quit()
  287. {
  288. MIDI_core::GlobalQuit();
  289. }
  290. void GetFileInfo(const char *url, char *title, int *len)
  291. {
  292. if (!url || !*url)
  293. {
  294. url=cur_file;
  295. }
  296. if (len) *len=0;
  297. if (title) *title=0;
  298. char ks=0;
  299. bool file_local=0;
  300. MIDI_file * file=0;
  301. if (MIDI_core::getFile() && !_stricmp(url,MIDI_core::getFile()->path))
  302. {
  303. file = MIDI_core::getFile()->AddRef();
  304. }
  305. if (!file)
  306. {
  307. file = wa2_open_file(url);
  308. if (!file) {
  309. return;
  310. }
  311. file_local=1;
  312. }
  313. if (len)
  314. *len=file->GetLength();
  315. if (title)
  316. file->GetTitle(title,256);
  317. file->Free();
  318. }
  319. BOOL CALLBACK InfoProc(HWND,UINT,WPARAM,LPARAM);
  320. int show_rmi_info(HWND w,MIDI_file* mf);
  321. int infoDlg(const char *fn, HWND hwnd)
  322. {
  323. int rv=1;
  324. MIDI_file *mf=wa2_open_file(fn);
  325. if (!mf) return INFOBOX_UNCHANGED;
  326. if (cfg_rmi_def) rv=show_rmi_info(hwnd,mf);
  327. else
  328. {
  329. rv = WASABI_API_DIALOGBOXPARAM(IDD_INFO,hwnd,InfoProc,(LPARAM)mf);
  330. }
  331. if (!rv && !_stricmp(mf->path,cur_file))
  332. {
  333. PostMessage(mod.hMainWindow,WM_USER,0,243);
  334. }
  335. mf->Free();
  336. return rv;
  337. }
  338. int InfoBox(const char *file, HWND parent)
  339. {
  340. if (!file) file=cur_file;
  341. return infoDlg(file,parent);
  342. }
  343. static char kill;
  344. static int pos_ms;
  345. static int seek_to;
  346. static bool out_open;
  347. DWORD WINAPI PlayThread(void*)
  348. {
  349. #ifdef USE_LOG
  350. log_write("PlayThread");
  351. #endif
  352. short * visbuf;
  353. char *sample_buf;
  354. int sr,bps,nch;
  355. pos_ms=0;
  356. int pos_base=0;
  357. int samp_wr=0;
  358. int max_l=0;
  359. MIDI_core::GetPCM(&sr,&nch,&bps);
  360. int s_size=576 * (bps/8) * nch;
  361. if (bps>16)
  362. {
  363. visbuf=(short*)malloc(576*2*nch);
  364. }
  365. else visbuf=0;
  366. sample_buf = (char*)malloc(576 * 2 * (bps/8) * nch);
  367. bool done=0;
  368. while(!(kill&1))
  369. {
  370. #ifdef USE_LOG
  371. log_write("main loop");
  372. #endif
  373. if (paused) {
  374. #ifdef USE_LOG
  375. log_write("paused");
  376. #endif
  377. Sleep(10);
  378. continue;
  379. }
  380. if (seek_to!=-1)
  381. {
  382. #ifdef USE_LOG
  383. log_write("seeking");
  384. #endif
  385. if (MIDI_core::SetPosition(seek_to))
  386. {
  387. pos_ms=seek_to;
  388. if (out_open)
  389. {
  390. mod.outMod->Flush(pos_ms);
  391. }
  392. pos_base=pos_ms;
  393. samp_wr=0;
  394. done=0;
  395. }
  396. kill&=~2;
  397. seek_to=-1;
  398. }
  399. if (done)
  400. {
  401. #ifdef USE_LOG
  402. log_write("done");
  403. #endif
  404. if (!mod.outMod->IsPlaying())
  405. {
  406. PostMessage(mod.hMainWindow,WM_WA_MPEG_EOF,0,0);
  407. break;
  408. }
  409. Sleep(10);continue;
  410. }
  411. #ifdef USE_LOG
  412. log_write("calling GetSamples");
  413. #endif
  414. int l=MIDI_core::GetSamples(sample_buf,s_size,&kill);
  415. if (kill&1) {
  416. #ifdef USE_LOG
  417. log_write("kill&1");
  418. #endif
  419. break;
  420. }
  421. if (kill&2) {
  422. #ifdef USE_LOG
  423. log_write("kill&2");
  424. #endif
  425. continue;
  426. }
  427. if (l<=0 && !paused)
  428. {
  429. #ifdef USE_LOG
  430. log_write("done(?)");
  431. #endif
  432. done=1;
  433. if (out_open)
  434. {
  435. mod.outMod->Write(sample_buf,0);
  436. continue;
  437. }
  438. else
  439. {
  440. PostMessage(mod.hMainWindow,WM_WA_MPEG_EOF,0,0);
  441. break;
  442. }
  443. }
  444. if (mod.dsp_isactive())
  445. {
  446. #ifdef USE_LOG
  447. log_write("DSP");
  448. #endif
  449. l=(8*l)/(bps*nch);
  450. l=mod.dsp_dosamples((short*)sample_buf,l,bps,nch,sr);
  451. l*=(nch*bps)/8;
  452. }
  453. if (out_open)
  454. {
  455. #ifdef USE_LOG
  456. log_write("sending to output");
  457. #endif
  458. if (kill&1) break;
  459. while(mod.outMod->CanWrite()<l && !kill) Sleep(2);
  460. if (kill&1) break;
  461. if (!kill) mod.outMod->Write((char*)sample_buf,l);
  462. }
  463. {
  464. char * vis=sample_buf;
  465. UINT vis_bps=bps;
  466. if (bps>16)
  467. {
  468. int n;
  469. UINT d=bps>>3;
  470. char * foo=sample_buf+d-2;
  471. for(n=0;n<576*nch;n++)
  472. {
  473. visbuf[n]=*(short*)foo;
  474. foo+=d;
  475. }
  476. vis=(char*)visbuf;
  477. vis_bps=16;
  478. }
  479. #ifdef USE_LOG
  480. log_write("doing vis");
  481. #endif
  482. mod.SAAddPCMData(vis,nch,vis_bps,pos_ms);
  483. mod.VSAAddPCMData(vis,nch,vis_bps,pos_ms);
  484. }
  485. samp_wr+=(8*l)/(bps*nch);
  486. pos_ms=pos_base+MulDiv(1000,samp_wr,sr);
  487. }
  488. free(sample_buf);
  489. if (visbuf) free(visbuf);
  490. return 0;
  491. }
  492. int initDefaultDeviceShit()
  493. {
  494. //CT> find default device if no device set
  495. MIDI_device * dev = MIDI_driver::find_device(cfg_driver,cfg_device);
  496. if(dev) return 1;
  497. //reinit to default
  498. MIDI_driver *driver=MIDI_driver::driver_enumerate(0);
  499. if(!driver) return 0;
  500. MIDI_device *device=driver->device_enumerate(0);
  501. if(!device) return 0;
  502. cfg_driver=driver->get_guid();
  503. cfg_device=device->get_guid();
  504. return 1;
  505. }
  506. int Play(const char *fn)
  507. {
  508. if(!initDefaultDeviceShit()) return 0;
  509. paused=0;
  510. seek_to=-1;
  511. kill=0;
  512. if (!MIDI_core::Init()) return 0;
  513. if (!MIDI_core::UsesOutput())
  514. {
  515. MIDI_core::SetVolume(volume);
  516. MIDI_core::SetPan(pan);
  517. }
  518. else
  519. {
  520. MIDI_core::SetVolume(255);
  521. MIDI_core::SetPan(0);
  522. }
  523. MIDI_file * file = wa2_open_file(fn);
  524. if (!file) return -1;
  525. int rv=MIDI_core::OpenFile(file);
  526. file->Free();
  527. if (rv==0)
  528. {
  529. MIDI_core::Close();
  530. return 1;
  531. }
  532. cur_file=fn;
  533. int sr,nch,bps;
  534. MIDI_core::GetPCM(&sr,&nch,&bps);
  535. {
  536. MIDI_file * mf=MIDI_core::getFile();
  537. UINT nc=0;
  538. if (mf) nc=mf->info.channels;
  539. mod.SetInfo(nc*10000,sr/1000,2,1);
  540. }
  541. if (MIDI_core::HavePCM())
  542. {
  543. int max_l=0;
  544. MIDI_core::GetPCM(&sr,&nch,&bps);
  545. if (MIDI_core::UsesOutput())
  546. {
  547. #ifdef USE_LOG
  548. log_write("output init");
  549. #endif
  550. max_l=mod.outMod->Open(sr,nch,bps,-1,-1);
  551. if (max_l<0)
  552. {
  553. MIDI_core::Close();
  554. return 1;
  555. }
  556. out_open=1;
  557. mod.outMod->SetVolume(volume);
  558. mod.outMod->SetPan(pan);
  559. }
  560. mod.SAVSAInit(max_l,sr);
  561. mod.VSASetInfo(sr,nch);
  562. #ifdef USE_LOG
  563. log_write("Creating thread");
  564. #endif
  565. DWORD id;
  566. thread=CreateThread(0,0,PlayThread,0,CREATE_SUSPENDED,&id);
  567. #ifndef _DEBUG
  568. SetThreadPriority(thread,THREAD_PRIORITY_TIME_CRITICAL);
  569. #endif
  570. ResumeThread(thread);
  571. }
  572. else
  573. {
  574. #ifdef USE_LOG
  575. log_write("threadless mode");
  576. #endif
  577. thread=0;
  578. }
  579. return 0;
  580. }
  581. void Pause()
  582. {
  583. if (MIDI_core::HavePlayer() && !paused)
  584. {
  585. MIDI_core::Pause(paused=1);
  586. if (MIDI_core::UsesOutput()) mod.outMod->Pause(1);
  587. }
  588. }
  589. void UnPause()
  590. {
  591. if (MIDI_core::HavePlayer() && paused)
  592. {
  593. MIDI_core::Pause(paused=0);
  594. if (MIDI_core::UsesOutput())
  595. {
  596. mod.outMod->Flush(0);
  597. mod.outMod->Pause(0);
  598. }
  599. }
  600. }
  601. int IsPaused()
  602. {
  603. return paused;
  604. }
  605. void Stop()
  606. {
  607. if (thread)
  608. {
  609. kill|=1;
  610. WaitForSingleObject(thread,INFINITE);
  611. CloseHandle(thread);
  612. thread=0;
  613. mod.SAVSADeInit();
  614. if (out_open)
  615. {
  616. out_open=0;
  617. mod.outMod->Close();
  618. }
  619. }
  620. MIDI_core::Close();
  621. }
  622. void EQSet(int on, char data[10], int preamp)
  623. {
  624. }
  625. int GetLength()
  626. {
  627. return MIDI_core::GetLength();
  628. }
  629. int GetOutputTime()
  630. {
  631. if (seek_to!=-1) return seek_to;
  632. if (thread && MIDI_core::UsesOutput()) return pos_ms+mod.outMod->GetOutputTime()-mod.outMod->GetWrittenTime();
  633. else return MIDI_core::GetPosition();
  634. }
  635. void SetOutputTime(int t)
  636. {
  637. if (thread)
  638. {
  639. seek_to=t;
  640. kill|=2;
  641. }
  642. else MIDI_core::SetPosition(t);
  643. }
  644. void SetVolume(int v)
  645. {
  646. volume=v;
  647. if (MIDI_core::UsesOutput()) mod.outMod->SetVolume(v);
  648. else MIDI_core::SetVolume(v);
  649. }
  650. void SetPan(int p)
  651. {
  652. pan=p;
  653. if (MIDI_core::UsesOutput()) mod.outMod->SetPan(p);
  654. else MIDI_core::SetPan(p);
  655. }
  656. In_Module mod=
  657. {
  658. IN_VER_RET,
  659. "nullsoft(in_midi.dll)",
  660. 0,0,
  661. fmts_string,
  662. 1,
  663. 1,
  664. Config,
  665. About,
  666. Init,
  667. Quit,
  668. GetFileInfo,
  669. InfoBox,
  670. MIDI_core::IsOurFile,
  671. Play,
  672. Pause,
  673. UnPause,
  674. IsPaused,
  675. Stop,
  676. GetLength,
  677. GetOutputTime,
  678. SetOutputTime,
  679. SetVolume,
  680. SetPan,
  681. 0,0,0,0,0,0,0,0,0,0,0,
  682. EQSet,
  683. 0,
  684. 0,
  685. };
  686. extern "C"
  687. {
  688. __declspec( dllexport ) In_Module * winampGetInModule2()
  689. {
  690. return &mod;
  691. }
  692. }
  693. void MIDI_callback::NotifyEOF() {PostMessage(mod.hMainWindow,WM_WA_MPEG_EOF,0,0);}
  694. HWND MIDI_callback::GetMainWindow() {return mod.hMainWindow;}
  695. HINSTANCE MIDI_callback::GetInstance() {return mod.hDllInstance;}
  696. void MIDI_callback::Error(const char * tx)
  697. {
  698. #ifndef WINAMPX
  699. MessageBoxA(mod.hMainWindow,tx,0,MB_ICONERROR);
  700. #endif
  701. }
  702. BOOL APIENTRY DllMain(HANDLE hMod,DWORD r,void*)
  703. {
  704. if (r==DLL_PROCESS_ATTACH)
  705. {
  706. DisableThreadLibraryCalls((HMODULE)hMod);
  707. }
  708. return 1;
  709. }
  710. void MIDI_callback::Idle(int ms)
  711. {
  712. int start = timeGetTime();
  713. do Sleep(1); while( (int)timeGetTime() - start < ms);
  714. }