convert.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781
  1. /** (c) Nullsoft, Inc. C O N F I D E N T I A L
  2. ** Filename:
  3. ** Project:
  4. ** Description:
  5. ** Author:
  6. ** Created:
  7. **/
  8. #include "main.h"
  9. #include "resource.h"
  10. #include "../nsv/enc_if.h"
  11. #include "../nu/threadname.h"
  12. #include "../nu/AutoWideFn.h"
  13. #include "../nu/AutoCharFn.h"
  14. #include "DecodeFile.h"
  15. extern DecodeFile *decodeFile;
  16. static wchar_t DLL_Dir[MAX_PATH];
  17. static intptr_t getEncoderFromFolder(const wchar_t *spec, int bps, int nch, int srate, int dstf, const wchar_t *curdir, int create, HMODULE *pmod, HWND hParent, converterEnumFmtStruct *enumCrap, char * inifile)
  18. {
  19. WIN32_FIND_DATAW fd = {0};
  20. wchar_t buf[MAX_PATH*2 + 1] = {0};
  21. PathCombineW(buf, curdir, spec);
  22. if (pmod) *pmod = NULL;
  23. HANDLE h = FindFirstFileW(buf, &fd);
  24. if (h != INVALID_HANDLE_VALUE)
  25. {
  26. do
  27. {
  28. PathCombineW(buf, curdir, fd.cFileName);
  29. HMODULE mod = LoadLibraryW(buf);
  30. if (mod)
  31. {
  32. // passes winamp's hwnd to the encoder (if supporting it)
  33. void (*swh)(HWND hwnd);
  34. *((void **)&swh) = GetProcAddress(mod, "SetWinampHWND");
  35. if (swh)
  36. {
  37. swh(hMainWindow);
  38. }
  39. if (enumCrap)
  40. {
  41. unsigned int (*gat)(int idx, char *desc);
  42. *((void **)&gat) = GetProcAddress(mod, "GetAudioTypes3");
  43. if (gat)
  44. {
  45. int i = 0;
  46. for (;;)
  47. {
  48. char desc[1024] = {0};
  49. unsigned int type = gat(i++, desc);
  50. if (!type) break;
  51. enumCrap->enumProc(enumCrap->user_data, desc, type);
  52. }
  53. }
  54. }
  55. else
  56. {
  57. void (*ExtAudio3)(HWND hwndParent, int *ex, int ex_len);
  58. *((void **)&ExtAudio3) = GetProcAddress(mod, "ExtAudio3");
  59. if (ExtAudio3) ExtAudio3(hMainWindow, NULL, 0);
  60. AudioCoder *ac = 0;
  61. AudioCoder *(*ca)(int nch, int srate, int bps, unsigned int srct, unsigned int *outt, char *configfile);
  62. *((void **)&ca) = GetProcAddress(mod, "CreateAudio3");
  63. if (create == 0)
  64. {
  65. HWND (*ca)(HWND hwndParent, HINSTANCE hinst, unsigned int outt, char *configfile);
  66. *((void**)&ca) = GetProcAddress(mod, "ConfigAudio3");
  67. if (ca)
  68. {
  69. HWND h = ca(hParent, mod, dstf, inifile?inifile:INI_FILEA);
  70. if (h)
  71. {
  72. *pmod = mod;
  73. return (intptr_t)h;
  74. }
  75. }
  76. }
  77. //if (ca && (ac=ca(nch,srate,bps,srct,outt,configfile))) return ac;
  78. if (create == 1 && ca && (ac = ca(nch, srate, bps, mmioFOURCC('P', 'C', 'M', ' '), (unsigned int *) & dstf, inifile?inifile:INI_FILEA))) //FUCKO: input format
  79. {
  80. *pmod = mod;
  81. return (intptr_t)ac;
  82. }
  83. if (create == 2) {
  84. unsigned int (*gat)(int idx, char *desc);
  85. *((void **)&gat) = GetProcAddress(mod, "GetAudioTypes3");
  86. if (gat)
  87. {
  88. int i = 0;
  89. for (;;)
  90. {
  91. char desc[1024] = {0};
  92. unsigned int type = gat(i++, desc);
  93. if (!type) break;
  94. if (type == dstf) {
  95. *pmod = mod;
  96. return 0;
  97. }
  98. }
  99. }
  100. }
  101. }
  102. FreeLibrary(mod);
  103. }
  104. }
  105. while (FindNextFileW(h, &fd));
  106. FindClose(h);
  107. }
  108. return 0;
  109. }
  110. static intptr_t getEncoder(int bps, int nch, int srate, int *destformat, int create, HMODULE *pmod, HWND parent, converterEnumFmtStruct *enumCrap = 0,char * inifile=0)
  111. {
  112. HKEY hKey = NULL;
  113. if (!DLL_Dir[0] && RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion",
  114. 0, KEY_READ, &hKey) == ERROR_SUCCESS)
  115. {
  116. DWORD l = sizeof(DLL_Dir);
  117. DWORD t = 0;
  118. if (RegQueryValueExW(hKey, L"CommonFilesDir", NULL, &t, (LPBYTE)DLL_Dir, &l ) != ERROR_SUCCESS || t != REG_SZ)
  119. DLL_Dir[0] = 0;
  120. PathAppendW(DLL_Dir, L"NSV");
  121. RegCloseKey(hKey);
  122. }
  123. if (!DLL_Dir[0]) GetTempPathW(sizeof(DLL_Dir)/sizeof(*DLL_Dir), DLL_Dir);
  124. //look in plugins folder
  125. int ret;
  126. if (ret = getEncoderFromFolder(L"enc_*.dll", bps, nch, srate, destformat[0], PLUGINDIR, create, pmod, parent, enumCrap,inifile))
  127. return ret;
  128. if (GetPrivateProfileIntW(AutoWide(app_name), L"scannsv", 0, INI_FILE))
  129. {
  130. //look in common files folder
  131. if (ret = getEncoderFromFolder(L"nsv_coder_*.dll", bps, nch, srate, destformat[0], DLL_Dir, create, pmod, parent, enumCrap,inifile))
  132. return ret;
  133. }
  134. return 0;
  135. }
  136. static DWORD WINAPI convertThread(void *param)
  137. {
  138. convertFileStruct *cfs = (convertFileStruct *)param;
  139. ifc_audiostream *decoder = cfs->decoder;
  140. HANDLE fh = cfs->file_handle;
  141. AudioCoder *ac = cfs->audio_coder;
  142. HMODULE mod = cfs->encoder_mod;
  143. int destformat = cfs->destformat[0];
  144. int bps = cfs->bps;
  145. int nch = cfs->channels;
  146. //int srate = cfs->sample_rate;
  147. size_t bytes_per_packet = nch*(bps/8);
  148. size_t ret = 0;
  149. SetThreadName((DWORD)-1, "Transcode");
  150. cfs->bytes_done = 0;
  151. cfs->bytes_out = 0;
  152. DWORD laststatpost = 0;
  153. do
  154. {
  155. int error=0;
  156. char buf[65536] = {0};
  157. size_t buf_size = sizeof(buf);
  158. buf_size -= (buf_size % bytes_per_packet); // don't read half a sample or only some of the channels!
  159. ret = decoder->ReadAudio(buf, buf_size, &cfs->killswitch, &error);
  160. if (destformat == mmioFOURCC('P', 'C', 'M', ' ') /* || destformat==mmioFOURCC('W','A','V',' ')*/)
  161. {
  162. //FUCKO: resample in desired format
  163. DWORD a = 0;
  164. if (ret > 0) WriteFile(fh, buf, (DWORD)ret, &a, NULL);
  165. cfs->bytes_out += a;
  166. }
  167. else
  168. {
  169. int framepos = 0;
  170. int avail = (int) ret;
  171. char *in = buf;
  172. char out[32768] = {0};
  173. // WM encoding needs to know that you're going to be done, before you stop calling Encode(...)
  174. if ( ret == 0 )
  175. {
  176. if (ac && mod)
  177. {
  178. void (*finish)(const char *filename, AudioCoder *coder);
  179. *((void **)&finish) = GetProcAddress(mod, "PrepareToFinish");
  180. if (finish)
  181. {
  182. finish(cfs->destfile, ac);
  183. }
  184. }
  185. }
  186. for (;;)
  187. {
  188. int in_used = 0;
  189. int v = ac->Encode(framepos++, in, avail, &in_used, out, sizeof(out));
  190. if (v > 0)
  191. {
  192. DWORD a = 0;
  193. WriteFile(fh, out, v, &a, NULL);
  194. cfs->bytes_out += v;
  195. }
  196. if (in_used > 0)
  197. {
  198. avail -= in_used;
  199. in += in_used;
  200. }
  201. if (!v && !in_used) break;
  202. }
  203. }
  204. cfs->bytes_done += (int)ret;
  205. if (GetTickCount() - laststatpost > 1000)
  206. {
  207. SendMessageW(cfs->callbackhwnd, WM_WA_IPC, (int)((double)cfs->bytes_done*100.0 / (double)cfs->bytes_total), IPC_CB_CONVERT_STATUS);
  208. laststatpost = GetTickCount();
  209. }
  210. }
  211. while (!cfs->killswitch && ret > 0);
  212. CloseHandle(fh);
  213. if (ac && mod)
  214. {
  215. void (*finish)(const char *filename, AudioCoder *coder);
  216. *((void **)&finish) = GetProcAddress(mod, "FinishAudio3");
  217. if (finish)
  218. {
  219. finish(cfs->destfile, ac);
  220. }
  221. }
  222. decodeFile->CloseAudio(decoder);
  223. if (!cfs->killswitch) PostMessageW(cfs->callbackhwnd, WM_WA_IPC, 0, IPC_CB_CONVERT_DONE);
  224. return 1;
  225. }
  226. static DWORD WINAPI convertThreadW(void *param)
  227. {
  228. convertFileStructW *cfs = (convertFileStructW *)param;
  229. ifc_audiostream *decoder = (ifc_audiostream *)cfs->decoder;
  230. HANDLE fh = cfs->file_handle;
  231. AudioCoder *ac = cfs->audio_coder;
  232. HMODULE mod = cfs->encoder_mod;
  233. int destformat = cfs->destformat[0];
  234. int bps = cfs->bps;
  235. int nch = cfs->channels;
  236. //int srate = cfs->sample_rate;
  237. size_t bytes_per_packet = nch*(bps/8);
  238. size_t ret = 0;
  239. SetThreadName((DWORD)-1, "Transcode");
  240. cfs->bytes_done = 0;
  241. cfs->bytes_out = 0;
  242. DWORD laststatpost = 0;
  243. do
  244. {
  245. int error=0;
  246. char buf[65536] = {0};
  247. size_t buf_size = sizeof(buf);
  248. buf_size -= (buf_size % bytes_per_packet); // don't read half a sample or only some of the channels!
  249. ret = decoder->ReadAudio(buf, buf_size, &cfs->killswitch, &error);
  250. if (destformat == mmioFOURCC('P', 'C', 'M', ' ') /* || destformat==mmioFOURCC('W','A','V',' ')*/)
  251. {
  252. //FUCKO: resample in desired format
  253. DWORD a = 0;
  254. if (ret > 0) WriteFile(fh, buf, (DWORD)ret, &a, NULL);
  255. cfs->bytes_out += a;
  256. }
  257. else
  258. {
  259. int framepos = 0;
  260. int avail = (int) ret;
  261. char *in = buf;
  262. char out[32768] = {0};
  263. // WM encoding needs to know that you're going to be done, before you stop calling Encode(...)
  264. if ( ret == 0 )
  265. {
  266. if (ac && mod)
  267. {
  268. // try unicode first
  269. void (*finishW)(const wchar_t *filename, AudioCoder *coder);
  270. *((void **)&finishW) = GetProcAddress(mod, "PrepareToFinishW");
  271. if (finishW)
  272. {
  273. finishW(cfs->destfile, ac);
  274. }
  275. else // otherwise, pass it the 8.3 filename
  276. {
  277. void (*finish)(const char *filename, AudioCoder *coder);
  278. *((void **)&finish) = GetProcAddress(mod, "PrepareToFinish");
  279. if (finish)
  280. {
  281. finish(AutoCharFn(cfs->destfile), ac);
  282. }
  283. }
  284. }
  285. }
  286. for (;;)
  287. {
  288. int in_used = 0;
  289. int v = ac->Encode(framepos++, in, avail, &in_used, out, sizeof(out));
  290. if (v > 0)
  291. {
  292. DWORD a = 0;
  293. WriteFile(fh, out, v, &a, NULL);
  294. cfs->bytes_out += v;
  295. }
  296. if (in_used > 0)
  297. {
  298. avail -= in_used;
  299. in += in_used;
  300. }
  301. if (!v && !in_used) break;
  302. }
  303. }
  304. cfs->bytes_done += (int)ret;
  305. if (GetTickCount() - laststatpost > 1000)
  306. {
  307. SendMessageW(cfs->callbackhwnd, WM_WA_IPC, (int)((double)cfs->bytes_done*100.0 / (double)cfs->bytes_total), IPC_CB_CONVERT_STATUS);
  308. laststatpost = GetTickCount();
  309. }
  310. }
  311. while (!cfs->killswitch && ret > 0);
  312. CloseHandle(fh);
  313. if (ac && mod)
  314. {
  315. void (*finishW)(const wchar_t *filename, AudioCoder *coder);
  316. *((void **)&finishW) = GetProcAddress(mod, "FinishAudio3W");
  317. if (finishW)
  318. {
  319. finishW(cfs->destfile, ac);
  320. }
  321. else // otherwise, try the 8.3 filename
  322. {
  323. void (*finish)(const char *filename, AudioCoder *coder);
  324. *((void **)&finish) = GetProcAddress(mod, "FinishAudio3");
  325. if (finish)
  326. {
  327. finish(AutoCharFn(cfs->destfile), ac);
  328. }
  329. }
  330. }
  331. decodeFile->CloseAudio(decoder);
  332. if (!cfs->killswitch) PostMessageW(cfs->callbackhwnd, WM_WA_IPC, 0, IPC_CB_CONVERT_DONE);
  333. return 1;
  334. }
  335. // due to the language support, we can't just now return the string in cfs->error
  336. // but instead have to have it in a static string so it can be accessed once we
  337. // have returned without issues from later use of getString and it's buffer usage
  338. static char errorStr[2048];
  339. int convert_file(convertFileStruct *cfs)
  340. {
  341. // clear the buffer on starting otherwise we may return an invalid error message
  342. //memset(&errorStr, 0, sizeof(errorStr));
  343. errorStr[0]=0;
  344. if (cfs->destfile && cfs->sourcefile && !_stricmp(cfs->destfile, cfs->sourcefile))
  345. {
  346. cfs->error = getString(IDS_CONV_SRC_EQUALS_DEST,errorStr,2048);
  347. return 0;
  348. }
  349. AudioParameters parameters;
  350. ifc_audiostream *decoder = decodeFile->OpenAudioBackground(AutoWideFn(cfs->sourcefile), &parameters);
  351. cfs->bytes_total= (int)(parameters.sizeBytes?parameters.sizeBytes:-1);
  352. if (!decoder)
  353. {
  354. switch(parameters.errorCode)
  355. {
  356. case API_DECODEFILE_UNSUPPORTED:
  357. cfs->error = getString(IDS_CONV_DECODER_MISSING,errorStr,2048);
  358. return 0;
  359. case API_DECODEFILE_NO_INTERFACE:
  360. cfs->error = getString(IDS_CONV_INPUT_PLUGIN_NOT_SUPPORTING,errorStr,2048);
  361. return 0;
  362. case API_DECODEFILE_NO_RIGHTS:
  363. cfs->error = getString(IDS_CONV_DRM_DECODE_FAIL,errorStr,2048);
  364. return 0;
  365. case API_DECODEFILE_FAIL_NO_WARN:
  366. return 0;
  367. default:
  368. cfs->error = getString(IDS_CONV_ERROR_OPEN_FILE,errorStr,2048);
  369. return 0;
  370. }
  371. }
  372. cfs->decoder=0;
  373. cfs->convert_thread=0;
  374. cfs->file_handle=0;
  375. cfs->audio_coder=0;
  376. cfs->encoder_mod=0;
  377. cfs->bps=0;
  378. cfs->channels=0;
  379. cfs->sample_rate=0;
  380. //find the encoding DLL
  381. if (cfs->destformat[0] != mmioFOURCC('P', 'C', 'M', ' '))
  382. {
  383. HMODULE mod = NULL;
  384. char * inifile = NULL;
  385. if(cfs->destformat[6] == mmioFOURCC('I','N','I',' ')) inifile = (char*)cfs->destformat[7];
  386. AudioCoder *ac = (AudioCoder *)getEncoder(parameters.bitsPerSample, parameters.channels, parameters.sampleRate, (int *) & cfs->destformat, 1, &mod, NULL,0, inifile);
  387. if (!ac)
  388. {
  389. decodeFile->CloseAudio(decoder);
  390. cfs->error = getString(IDS_CONV_ERROR_OPEN_ENCODER,errorStr,2048);
  391. return 0;
  392. }
  393. cfs->audio_coder = ac;
  394. cfs->encoder_mod = mod;
  395. }
  396. cfs->killswitch = 0;
  397. cfs->decoder = decoder;
  398. cfs->bps = parameters.bitsPerSample;
  399. cfs->channels = parameters.channels;
  400. cfs->sample_rate = parameters.sampleRate;
  401. //open destination file
  402. HANDLE fh = CreateFileA(cfs->destfile, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  403. if ( fh == INVALID_HANDLE_VALUE )
  404. {
  405. decodeFile->CloseAudio(decoder);
  406. delete cfs->audio_coder;
  407. cfs->audio_coder = 0;
  408. cfs->error = getString(IDS_CONV_ERROR_OPEN_DEST,errorStr,2048);
  409. return 0;
  410. }
  411. cfs->file_handle = fh;
  412. DWORD id = 0;
  413. cfs->convert_thread = CreateThread(NULL, 0, convertThread, cfs, 0, &id);
  414. return 1;
  415. }
  416. static wchar_t errorStrW[2048];
  417. int convert_fileW(convertFileStructW *cfs)
  418. {
  419. // clear the buffer on starting otherwise we may return an invalid error message
  420. memset(&errorStrW, 0, sizeof(errorStrW));
  421. if (cfs->destfile && cfs->sourcefile && !_wcsicmp(cfs->destfile, cfs->sourcefile))
  422. {
  423. cfs->error = getStringW(IDS_CONV_SRC_EQUALS_DEST,errorStrW,2048);
  424. return 0;
  425. }
  426. AudioParameters parameters;
  427. ifc_audiostream *decoder = decodeFile->OpenAudioBackground(cfs->sourcefile, &parameters);
  428. cfs->bytes_total= (int)(parameters.sizeBytes?parameters.sizeBytes:-1);
  429. if (!decoder)
  430. {
  431. switch(parameters.errorCode)
  432. {
  433. case API_DECODEFILE_UNSUPPORTED:
  434. cfs->error = getStringW(IDS_CONV_DECODER_MISSING,errorStrW,2048);
  435. return 0;
  436. case API_DECODEFILE_NO_INTERFACE:
  437. cfs->error = getStringW(IDS_CONV_INPUT_PLUGIN_NOT_SUPPORTING,errorStrW,2048);
  438. return 0;
  439. case API_DECODEFILE_NO_RIGHTS:
  440. cfs->error = getStringW(IDS_CONV_DRM_DECODE_FAIL,errorStrW,2048);
  441. return 0;
  442. case API_DECODEFILE_FAIL_NO_WARN:
  443. return 0;
  444. default:
  445. cfs->error = getStringW(IDS_CONV_ERROR_OPEN_FILE,errorStrW,2048);
  446. return 0;
  447. }
  448. }
  449. cfs->decoder=0;
  450. cfs->convert_thread=0;
  451. cfs->file_handle=0;
  452. cfs->audio_coder=0;
  453. cfs->encoder_mod=0;
  454. cfs->bps=0;
  455. cfs->channels=0;
  456. cfs->sample_rate=0;
  457. //find the encoding DLL
  458. if (cfs->destformat[0] != mmioFOURCC('P', 'C', 'M', ' '))
  459. {
  460. HMODULE mod = NULL;
  461. char * inifile = NULL;
  462. if(cfs->destformat[6] == mmioFOURCC('I','N','I',' ')) inifile = (char*)cfs->destformat[7];
  463. AudioCoder *ac = (AudioCoder *)getEncoder(parameters.bitsPerSample, parameters.channels, parameters.sampleRate, (int *) & cfs->destformat, 1, &mod, NULL,0, inifile);
  464. if (!ac)
  465. {
  466. decodeFile->CloseAudio(decoder);
  467. cfs->error = getStringW(IDS_CONV_ERROR_OPEN_ENCODER,errorStrW,2048);
  468. return 0;
  469. }
  470. cfs->audio_coder = ac;
  471. cfs->encoder_mod = mod;
  472. }
  473. cfs->killswitch = 0;
  474. cfs->decoder = decoder;
  475. cfs->bps = parameters.bitsPerSample;
  476. cfs->channels = parameters.channels;
  477. cfs->sample_rate = parameters.sampleRate;
  478. //open destination file
  479. HANDLE fh = CreateFileW(cfs->destfile, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  480. if ( fh == INVALID_HANDLE_VALUE )
  481. {
  482. decodeFile->CloseAudio(decoder);
  483. delete cfs->audio_coder;
  484. cfs->audio_coder = 0;
  485. FreeLibrary(cfs->encoder_mod);
  486. cfs->encoder_mod = 0;
  487. cfs->error = getStringW(IDS_CONV_ERROR_OPEN_DEST,errorStrW,2048);
  488. return 0;
  489. }
  490. cfs->file_handle = fh;
  491. DWORD id = 0;
  492. cfs->convert_thread = CreateThread(NULL, 0, convertThreadW, cfs, 0, &id);
  493. return 1;
  494. }
  495. int convert_file_test(convertFileStructW *cfs)
  496. {
  497. // clear the buffer on starting otherwise we may return an invalid error message
  498. errorStrW[0]=0;
  499. AudioCoder *ac=0;
  500. HMODULE mod=0;
  501. if (cfs->destfile && cfs->sourcefile && !_wcsicmp(cfs->destfile, cfs->sourcefile))
  502. {
  503. cfs->error = getStringW(IDS_CONV_SRC_EQUALS_DEST,errorStrW,2048);
  504. return 0;
  505. }
  506. AudioParameters parameters;
  507. ifc_audiostream *decoder = decodeFile->OpenAudioBackground(cfs->sourcefile, &parameters);
  508. cfs->bytes_total= (int)(parameters.sizeBytes?parameters.sizeBytes:-1);
  509. if (!decoder)
  510. {
  511. switch(parameters.errorCode)
  512. {
  513. case API_DECODEFILE_UNSUPPORTED:
  514. cfs->error = getStringW(IDS_CONV_DECODER_MISSING,errorStrW,2048);
  515. return 0;
  516. case API_DECODEFILE_NO_INTERFACE:
  517. cfs->error = getStringW(IDS_CONV_INPUT_PLUGIN_NOT_SUPPORTING,errorStrW,2048);
  518. return 0;
  519. case API_DECODEFILE_NO_RIGHTS:
  520. cfs->error = getStringW(IDS_CONV_DRM_DECODE_FAIL,errorStrW,2048);
  521. return 0;
  522. case API_DECODEFILE_FAIL_NO_WARN:
  523. return 0;
  524. default:
  525. cfs->error = getStringW(IDS_CONV_ERROR_OPEN_FILE,errorStrW,2048);
  526. return 0;
  527. }
  528. }
  529. decodeFile->CloseAudio(decoder);
  530. cfs->decoder=0;
  531. cfs->convert_thread=0;
  532. cfs->file_handle=0;
  533. cfs->audio_coder=0;
  534. cfs->encoder_mod=0;
  535. cfs->bps=0;
  536. cfs->channels=0;
  537. cfs->sample_rate=0;
  538. //find the encoding DLL
  539. if (cfs->destformat[0] != mmioFOURCC('P', 'C', 'M', ' '))
  540. {
  541. char * inifile = NULL;
  542. if(cfs->destformat[6] == mmioFOURCC('I','N','I',' ')) inifile = (char*)cfs->destformat[7];
  543. ac = (AudioCoder *)getEncoder(parameters.bitsPerSample, parameters.channels, parameters.sampleRate, (int *) & cfs->destformat, 1, &mod, NULL,0, inifile);
  544. if (!ac)
  545. {
  546. cfs->error = getStringW(IDS_CONV_ERROR_OPEN_ENCODER,errorStrW,2048);
  547. return 0;
  548. }
  549. cfs->audio_coder = ac;
  550. cfs->encoder_mod = mod;
  551. }
  552. cfs->killswitch = 0;
  553. cfs->decoder = decoder;
  554. cfs->bps = parameters.bitsPerSample;
  555. cfs->channels = parameters.channels;
  556. cfs->sample_rate = parameters.sampleRate;
  557. //open destination file
  558. HANDLE fh = CreateFileW(cfs->destfile, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  559. if ( fh == INVALID_HANDLE_VALUE )
  560. {
  561. delete ac;
  562. cfs->audio_coder = 0;
  563. FreeLibrary(mod);
  564. cfs->encoder_mod = 0;
  565. cfs->error = getStringW(IDS_CONV_ERROR_OPEN_DEST,errorStrW,2048);
  566. return 0;
  567. }
  568. delete ac;
  569. cfs->audio_coder = 0;
  570. FreeLibrary(mod);
  571. cfs->encoder_mod = 0;
  572. CloseHandle(fh);
  573. return 1;
  574. }
  575. void convert_end(convertFileStruct *cfs)
  576. {
  577. HANDLE handle = cfs->convert_thread;
  578. cfs->killswitch = 1;
  579. if (handle && handle != INVALID_HANDLE_VALUE)
  580. {
  581. WaitForSingleObject(handle, 20000);
  582. CloseHandle(handle);
  583. cfs->convert_thread = INVALID_HANDLE_VALUE;
  584. }
  585. delete(cfs->audio_coder);
  586. cfs->audio_coder = 0;
  587. HMODULE mod = cfs->encoder_mod;
  588. if (mod)
  589. {
  590. FreeLibrary(mod);
  591. cfs->encoder_mod = 0;
  592. }
  593. }
  594. void convert_endW(convertFileStructW *cfs)
  595. {
  596. HANDLE handle = cfs->convert_thread;
  597. cfs->killswitch = 1;
  598. if (handle && handle != INVALID_HANDLE_VALUE)
  599. {
  600. WaitForSingleObject(handle, 20000);
  601. CloseHandle(handle);
  602. cfs->convert_thread = INVALID_HANDLE_VALUE;
  603. }
  604. delete(cfs->audio_coder);
  605. cfs->audio_coder = 0;
  606. HMODULE mod = cfs->encoder_mod;
  607. if (mod)
  608. {
  609. FreeLibrary(mod);
  610. cfs->encoder_mod = 0;
  611. }
  612. }
  613. void convert_enumfmts(converterEnumFmtStruct *cefs)
  614. {
  615. // cefs->enumProc(cefs->user_data, ".WAV output", mmioFOURCC('W', 'A', 'V', ' '));
  616. int destformat[8] = {0};
  617. getEncoder(0, 0, 0, (int *)&destformat, 0, NULL, 0, cefs);
  618. }
  619. HWND convert_config(convertConfigStruct *ccs)
  620. {
  621. HMODULE mod = NULL;
  622. int destformat[8] = {ccs->format, };
  623. char * inifile = NULL;
  624. if(ccs->extra_data[6] == mmioFOURCC('I','N','I',' '))
  625. inifile = (char*)ccs->extra_data[7];
  626. HWND h = (HWND)getEncoder(0, 0, 0, (int *) & destformat, 0, &mod, ccs->hwndParent,0,inifile);
  627. ccs->hwndConfig = h;
  628. ccs->extra_data[0] = (intptr_t)mod;
  629. return h;
  630. }
  631. void convert_config_end(convertConfigStruct *ccs)
  632. {
  633. HMODULE mod = (HMODULE)ccs->extra_data[0];
  634. DestroyWindow(ccs->hwndConfig);
  635. if (mod) FreeLibrary(mod);
  636. }
  637. void convert_setPriority(convertSetPriority *csp)
  638. {
  639. if (csp->cfs)
  640. {
  641. HANDLE handle = csp->cfs->convert_thread;
  642. if (handle)
  643. SetThreadPriority(handle, csp->priority);
  644. else
  645. {
  646. //FUCKO> handle when separate process
  647. }
  648. }
  649. }
  650. void convert_setPriorityW(convertSetPriorityW *csp)
  651. {
  652. if (csp->cfs)
  653. {
  654. HANDLE handle = (void *)csp->cfs->convert_thread;
  655. if (handle)
  656. SetThreadPriority(handle, csp->priority);
  657. else
  658. {
  659. //FUCKO> handle when separate process
  660. }
  661. }
  662. }
  663. int convert_setConfigItem(convertConfigItem *cci) {
  664. int ret = 0;
  665. int destformat[8] = {(int)cci->format, };
  666. HMODULE mod = NULL;
  667. if (!cci->configfile) cci->configfile=INI_FILEA;
  668. getEncoder(0,0,0, (int *) & destformat, 2, &mod, NULL,0,cci->configfile);
  669. if(mod) {
  670. int (*sci)(unsigned int outt, char *item, char *data, char *configfile);
  671. *((void **)&sci) = GetProcAddress(mod, "SetConfigItem");
  672. if(sci) {
  673. ret = sci(cci->format,cci->item,cci->data,cci->configfile);
  674. }
  675. FreeLibrary(mod);
  676. }
  677. return ret;
  678. }
  679. int convert_getConfigItem(convertConfigItem *cci) {
  680. int ret = 0;
  681. int destformat[8] = {(int)cci->format, };
  682. HMODULE mod = NULL;
  683. if (!cci->configfile) cci->configfile=INI_FILEA;
  684. getEncoder(0,0,0, (int *) & destformat, 2, &mod, NULL,0,cci->configfile);
  685. if(mod) {
  686. int (*gci)(unsigned int outt, char *item, char *data, int len, char *configfile);
  687. *((void **)&gci) = GetProcAddress(mod, "GetConfigItem");
  688. if(gci) {
  689. ret = gci(cci->format,cci->item,cci->data,cci->len,cci->configfile);
  690. }
  691. FreeLibrary(mod);
  692. }
  693. return ret;
  694. }