1
0

cdrip.cpp 35 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061
  1. #include "main.h"
  2. #include <windowsx.h>
  3. #include "resource.h"
  4. #include "..\nu\listview.h"
  5. #include "../nu/DialogSkinner.h"
  6. #include "../nu/ChildSizer.h"
  7. #include "config.h"
  8. #include "../winamp/wa_ipc.h"
  9. #include "..\..\General\gen_ml/gaystring.h"
  10. #include <stdio.h>
  11. #include <shlobj.h>
  12. #include <time.h>
  13. #include "../nu/AutoChar.h"
  14. #include "../nu/AutoCharFn.h"
  15. #include "../nu/AutoWide.h"
  16. #include "ReplayGain.h"
  17. #include "M3UWriter.h"
  18. #include "PLSWriter.h"
  19. #include "./settings.h"
  20. #include <shlwapi.h>
  21. #include <windows.h>
  22. #include <strsafe.h>
  23. extern unsigned int FileTimeToUnixTime(FILETIME *ft);
  24. static UINT uMsgRipperNotify = 0;
  25. static INT_PTR WINAPI DlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
  26. HWND CreateCDRipWindow(HWND hwndParent, CHAR cLetter)
  27. {
  28. return WASABI_API_CREATEDIALOGPARAMW(IDD_VIEW_CDROM_EX2, hwndParent, DlgProc, (LPARAM)cLetter);
  29. }
  30. //physically update metadata in a given file
  31. int updateFileInfo(char *filename, char *metadata, char *data)
  32. {
  33. extendedFileInfoStruct efis = {
  34. filename,
  35. metadata,
  36. data ? data : "",
  37. data ? strlen(data) : 0,
  38. };
  39. return (INT)(INT_PTR)SendMessage(plugin.hwndWinampParent, WM_WA_IPC, (WPARAM)&efis, IPC_SET_EXTENDED_FILE_INFO);
  40. }
  41. //physically update metadata in a given file
  42. int updateFileInfoW(wchar_t *filename, const wchar_t *metadata, const wchar_t *data)
  43. {
  44. extendedFileInfoStructW efis = {
  45. filename,
  46. metadata,
  47. data ? data : L"",
  48. data ? lstrlenW(data) : 0,
  49. };
  50. return (INT)(INT_PTR)SendMessage(plugin.hwndWinampParent, WM_WA_IPC, (WPARAM)&efis, IPC_SET_EXTENDED_FILE_INFOW);
  51. }
  52. static int m_extract_curtrack, m_extract_nb, m_extract_nb_total;
  53. static int m_db_has_upd;
  54. static convertFileStructW m_fcs;
  55. static wchar_t m_extract_src[64];
  56. static DWORD m_extract_time;
  57. static int m_extracting;
  58. static cdrip_params *m_rip_params;
  59. HWND m_extract_wnd = 0;
  60. static wchar_t m_last_total_status[512];
  61. static wchar_t m_last_item_status[512];
  62. static int m_cur_rg = 0;
  63. static int done = 0;
  64. bool RegisteredEncoder(DWORD fourcc)
  65. {
  66. if (fourcc == mmioFOURCC('M', 'P', '3', 'l')
  67. || fourcc == mmioFOURCC('A', 'A', 'C', 'H')
  68. || fourcc == mmioFOURCC('M', '4', 'A', 'H'))
  69. return true;
  70. else
  71. return false;
  72. }
  73. static void createDirForFile(char *str)
  74. {
  75. char *p = str;
  76. if ((p[0] == '\\' || p[0] == '/') && (p[1] == '\\' || p[1] == '/'))
  77. {
  78. p += 2;
  79. while (p && *p && *p != '\\' && *p != '/') p++;
  80. if (!p || !*p) return ;
  81. p++;
  82. while (p && *p && *p != '\\' && *p != '/') p++;
  83. }
  84. else
  85. {
  86. while (p && *p && *p != '\\' && *p != '/') p++;
  87. }
  88. while (p && *p)
  89. {
  90. while (p && *p != '\\' && *p != '/' && *p) p = CharNextA(p);
  91. if (p && *p)
  92. {
  93. char lp = *p;
  94. *p = 0;
  95. CreateDirectoryA(str, NULL);
  96. *p++ = lp;
  97. }
  98. }
  99. }
  100. static void createDirForFileW(wchar_t *str)
  101. {
  102. wchar_t *p = str;
  103. if ((p[0] ==L'\\' || p[0] ==L'/') && (p[1] ==L'\\' || p[1] ==L'/'))
  104. {
  105. p += 2;
  106. while (p && *p && *p !=L'\\' && *p !=L'/') p++;
  107. if (!p || !*p) return ;
  108. p++;
  109. while (p && *p && *p !=L'\\' && *p !=L'/') p++;
  110. }
  111. else
  112. {
  113. while (p && *p && *p !=L'\\' && *p !=L'/') p++;
  114. }
  115. while (p && *p)
  116. {
  117. while (p && *p !=L'\\' && *p !=L'/' && *p) p = CharNextW(p);
  118. if (p && *p)
  119. {
  120. wchar_t lp = *p;
  121. *p = 0;
  122. CreateDirectoryW(str, NULL);
  123. *p++ = lp;
  124. }
  125. }
  126. }
  127. static void LockCD(char cLetter, BOOL bLock)
  128. {
  129. wchar_t info[32] = {0};
  130. wchar_t name[] = L"cda://X";
  131. name[6] = cLetter;
  132. getFileInfoW(name, (bLock) ? L"cdlock" : L"cdunlock", info, sizeof(info)/sizeof(wchar_t));
  133. }
  134. static int m_pstat_bytesdone;
  135. static int m_pstat_bytesout;
  136. static int m_pstat_timedone;
  137. static int m_rip_done;
  138. static HWND m_hwndstatus;
  139. static W_ListView m_statuslist;
  140. static void NotifyInfoWindow(HWND hwnd, BOOL bForceRefresh)
  141. {
  142. HWND hwndParent;
  143. hwndParent = GetParent(hwnd);
  144. if (hwndParent) SendMessageW(hwndParent, WM_SHOWFILEINFO,
  145. (WPARAM) WISF_MESSAGE | ((bForceRefresh) ? WISF_FORCE : WISF_NORMAL),
  146. (LPARAM)WASABI_API_LNGSTRINGW(IDS_INFO_RIPPING));
  147. }
  148. static void ListView_OnItemChanged(HWND hwndDlg, NMLISTVIEW *pnmv)
  149. {
  150. if (LVIF_STATE & pnmv->uChanged)
  151. {
  152. if ((LVIS_FOCUSED & pnmv->uOldState) != (LVIS_FOCUSED & pnmv->uNewState))
  153. {
  154. NotifyInfoWindow(hwndDlg, TRUE);
  155. }
  156. }
  157. }
  158. static void Window_OnQueryInfo(HWND hwnd)
  159. {
  160. NotifyInfoWindow(hwnd, FALSE);
  161. }
  162. static INT_PTR Window_OnNotify(HWND hwndDlg, INT ctrlId, LPNMHDR phdr)
  163. {
  164. switch(phdr->idFrom)
  165. {
  166. case IDC_LIST2:
  167. switch(phdr->code)
  168. {
  169. case LVN_ITEMCHANGED: ListView_OnItemChanged(hwndDlg, (NMLISTVIEW*)phdr); break;
  170. }
  171. break;
  172. }
  173. return 0;
  174. }
  175. INT_PTR WINAPI DlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  176. {
  177. static ChildWndResizeItem ripwnd_rlist[] = {
  178. {IDC_LIST2, 0x0011},
  179. {IDC_CDINFO, 0x0000},
  180. {IDC_RIPOPTS, 0x0101},
  181. {IDC_CANCEL_RIP, 0x0101},
  182. {IDC_BTN_SHOWINFO, 0x1111},
  183. };
  184. INT_PTR a = (INT_PTR)dialogSkinner.Handle(hwndDlg, uMsg, wParam, lParam); if (a) return a;
  185. switch (uMsg)
  186. {
  187. case WM_SIZE:
  188. if (wParam != SIZE_MINIMIZED)
  189. {
  190. childSizer.Resize(hwndDlg, ripwnd_rlist, sizeof(ripwnd_rlist) / sizeof(ripwnd_rlist[0]));
  191. }
  192. break;
  193. case WM_PAINT:
  194. {
  195. int tab[] = { IDC_LIST2 | DCW_SUNKENBORDER};
  196. dialogSkinner.Draw(hwndDlg, tab, 1);
  197. }
  198. return 0;
  199. case WM_INITDIALOG:
  200. m_hwndstatus = hwndDlg;
  201. SendMessageW(GetParent(hwndDlg), WM_COMMAND, MAKEWPARAM(IDC_BTN_SHOWINFO, BN_EX_GETTEXT), (LPARAM)GetDlgItem(hwndDlg, IDC_BTN_SHOWINFO));
  202. m_statuslist.setwnd(GetDlgItem(hwndDlg, IDC_LIST2));
  203. m_statuslist.AddCol(WASABI_API_LNGSTRINGW(IDS_TRACK_NUMBER), g_view_metaconf->ReadInt(L"col_track", 60));
  204. m_statuslist.AddCol(WASABI_API_LNGSTRINGW(IDS_TITLE), g_view_metaconf->ReadInt(L"col_title", 200));
  205. m_statuslist.AddCol(WASABI_API_LNGSTRINGW(IDS_LENGTH), g_view_metaconf->ReadInt(L"col_len", 80));
  206. m_statuslist.AddCol(WASABI_API_LNGSTRINGW(IDS_STATUS), g_view_metaconf->ReadInt(L"col_status", 200));
  207. SetDlgItemText(hwndDlg, IDC_CDINFO, m_last_total_status);
  208. {
  209. int l = m_rip_params->ntracks;
  210. int x = 0;
  211. for (int i = 0;i < l;i++) if (m_rip_params->tracks[i])
  212. {
  213. wchar_t buf[1024] = {0};
  214. StringCchPrintf(buf, 1024, L"%d", i + 1);
  215. m_statuslist.InsertItem(x, buf, 0);
  216. m_statuslist.SetItemText(x, 1, m_rip_params->tracks[i]);
  217. StringCchPrintf(buf, 512, L"%d:%02d", m_rip_params->lengths[i] / 60, m_rip_params->lengths[i] % 60);
  218. m_statuslist.SetItemText(x, 2, buf);
  219. if (i < m_extract_curtrack || m_rip_done)
  220. m_statuslist.SetItemText(x, 3, WASABI_API_LNGSTRINGW(IDS_COMPLETED));
  221. else if (i > m_extract_curtrack)
  222. m_statuslist.SetItemText(x, 3, WASABI_API_LNGSTRINGW(IDS_QUEUED));
  223. else
  224. {
  225. m_statuslist.SetItemText(x, 3, m_last_item_status[0] ? m_last_item_status : WASABI_API_LNGSTRINGW(IDS_RIPPING));
  226. }
  227. x++;
  228. }
  229. }
  230. if (!m_extract_wnd || m_rip_done)
  231. {
  232. SetDlgItemText(hwndDlg, IDC_CANCEL_RIP, WASABI_API_LNGSTRINGW(IDS_CLOSE));
  233. }
  234. if (g_config->ReadInt(L"cdripautoeject", 0)) CheckDlgButton(hwndDlg, IDC_CHECK2, BST_CHECKED);
  235. if (g_config->ReadInt(L"cdripautoplay", 0)) CheckDlgButton(hwndDlg, IDC_CHECK3, BST_CHECKED);
  236. if (g_config->ReadInt(L"cdripautoclose", 1)) CheckDlgButton(hwndDlg, IDC_CHECK1, BST_CHECKED);
  237. childSizer.Init(hwndDlg, ripwnd_rlist, sizeof(ripwnd_rlist) / sizeof(ripwnd_rlist[0]));
  238. ListView_SetTextColor(m_statuslist.getwnd(), dialogSkinner.Color(WADLG_ITEMFG));
  239. ListView_SetBkColor(m_statuslist.getwnd(), dialogSkinner.Color(WADLG_ITEMBG));
  240. ListView_SetTextBkColor(m_statuslist.getwnd(), dialogSkinner.Color(WADLG_ITEMBG));
  241. if(m_statuslist.getwnd())
  242. {
  243. MLSKINWINDOW sw;
  244. sw.hwndToSkin = m_statuslist.getwnd();
  245. sw.skinType = SKINNEDWND_TYPE_LISTVIEW;
  246. sw.style = SWLVS_FULLROWSELECT | SWLVS_DOUBLEBUFFER | SWLVS_ALTERNATEITEMS | SWS_USESKINFONT | SWS_USESKINCOLORS | SWS_USESKINCURSORS;
  247. MLSkinWindow(plugin.hwndLibraryParent, &sw);
  248. }
  249. NotifyInfoWindow(hwndDlg, TRUE);
  250. return 0;
  251. case WM_COMMAND:
  252. switch (LOWORD(wParam))
  253. {
  254. case IDC_RIPOPTS:
  255. {
  256. RECT r;
  257. HMENU menu = GetSubMenu(g_context_menus, 5);
  258. GetWindowRect((HWND)lParam, &r);
  259. CheckMenuItem(menu, ID_RIPOPTIONS_RIPPINGSTATUSWINDOW, g_config->ReadInt(L"cdripstatuswnd", 0) ? MF_CHECKED : MF_UNCHECKED);
  260. CheckMenuItem(menu, ID_RIPOPTIONS_EJECTCDWHENCOMPLETED, g_config->ReadInt(L"cdripautoeject", 0) ? MF_CHECKED : MF_UNCHECKED);
  261. CheckMenuItem(menu, ID_RIPOPTIONS_PLAYTRACKSWHENCOMPLETED, g_config->ReadInt(L"cdripautoplay", 0) ? MF_CHECKED : MF_UNCHECKED);
  262. CheckMenuItem(menu, ID_RIPOPTIONS_CLOSEVIEWWHENCOMPLETE, g_config->ReadInt(L"cdripautoclose", 0) ? MF_CHECKED : MF_UNCHECKED);
  263. int prio = g_config->ReadInt(L"extractprio", THREAD_PRIORITY_NORMAL);
  264. CheckMenuItem(menu, ID_RIPOPTIONS_PRIORITY_IDLE, prio == THREAD_PRIORITY_IDLE ? MF_CHECKED : MF_UNCHECKED);
  265. CheckMenuItem(menu, ID_RIPOPTIONS_PRIORITY_LOWEST, prio == THREAD_PRIORITY_LOWEST ? MF_CHECKED : MF_UNCHECKED);
  266. CheckMenuItem(menu, ID_RIPOPTIONS_PRIORITY_BELOWNORMAL, prio == THREAD_PRIORITY_BELOW_NORMAL ? MF_CHECKED : MF_UNCHECKED);
  267. CheckMenuItem(menu, ID_RIPOPTIONS_PRIORITY_NORMAL, prio == THREAD_PRIORITY_NORMAL ? MF_CHECKED : MF_UNCHECKED);
  268. CheckMenuItem(menu, ID_RIPOPTIONS_PRIORITY_ABOVENORMAL, prio == THREAD_PRIORITY_ABOVE_NORMAL ? MF_CHECKED : MF_UNCHECKED);
  269. CheckMenuItem(menu, ID_RIPOPTIONS_PRIORITY_HIGH, prio == THREAD_PRIORITY_HIGHEST ? MF_CHECKED : MF_UNCHECKED);
  270. int x = Menu_TrackPopup(plugin.hwndLibraryParent, menu,
  271. TPM_RIGHTBUTTON | TPM_LEFTBUTTON | TPM_BOTTOMALIGN |
  272. TPM_LEFTALIGN | TPM_NONOTIFY | TPM_RETURNCMD,
  273. r.left, r.top, hwndDlg, NULL);
  274. switch (x)
  275. {
  276. case ID_RIPOPTIONS_RIPPINGSTATUSWINDOW:
  277. {
  278. int x = g_config->ReadInt(L"cdripstatuswnd", 0);
  279. g_config->WriteInt(L"cdripstatuswnd", !x);
  280. ShowWindow(m_extract_wnd, x ? SW_HIDE : SW_SHOW);
  281. }
  282. break;
  283. case ID_RIPOPTIONS_EJECTCDWHENCOMPLETED:
  284. g_config->WriteInt(L"cdripautoeject", !g_config->ReadInt(L"cdripautoeject", 0));
  285. break;
  286. case ID_RIPOPTIONS_PLAYTRACKSWHENCOMPLETED:
  287. g_config->WriteInt(L"cdripautoplay", !g_config->ReadInt(L"cdripautoplay", 0));
  288. break;
  289. case ID_RIPOPTIONS_CLOSEVIEWWHENCOMPLETE:
  290. g_config->WriteInt(L"cdripautoclose", !g_config->ReadInt(L"cdripautoclose", 0));
  291. break;
  292. case ID_RIPOPTIONS_PRIORITY_IDLE:
  293. case ID_RIPOPTIONS_PRIORITY_LOWEST:
  294. case ID_RIPOPTIONS_PRIORITY_BELOWNORMAL:
  295. case ID_RIPOPTIONS_PRIORITY_NORMAL:
  296. case ID_RIPOPTIONS_PRIORITY_ABOVENORMAL:
  297. case ID_RIPOPTIONS_PRIORITY_HIGH:
  298. {
  299. int prio = THREAD_PRIORITY_NORMAL;
  300. if (x == ID_RIPOPTIONS_PRIORITY_IDLE) prio = THREAD_PRIORITY_IDLE;
  301. if (x == ID_RIPOPTIONS_PRIORITY_LOWEST) prio = THREAD_PRIORITY_LOWEST;
  302. if (x == ID_RIPOPTIONS_PRIORITY_BELOWNORMAL) prio = THREAD_PRIORITY_BELOW_NORMAL;
  303. if (x == ID_RIPOPTIONS_PRIORITY_ABOVENORMAL) prio = THREAD_PRIORITY_ABOVE_NORMAL;
  304. if (x == ID_RIPOPTIONS_PRIORITY_HIGH) prio = THREAD_PRIORITY_HIGHEST;
  305. g_config->WriteInt(L"extractprio", prio);
  306. convertSetPriorityW csp = {
  307. &m_fcs,
  308. prio,
  309. };
  310. SendMessage(plugin.hwndWinampParent, WM_WA_IPC, (WPARAM)&csp, IPC_CONVERT_SET_PRIORITYW);
  311. }
  312. break;
  313. }
  314. Sleep(100);
  315. MSG msg;
  316. while (PeekMessage(&msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)); //eat return
  317. }
  318. return 0;
  319. case IDC_CANCEL_RIP:
  320. {
  321. wchar_t title[64] = {0};
  322. if (!m_extract_wnd ||
  323. m_rip_done ||
  324. MessageBox(hwndDlg, WASABI_API_LNGSTRINGW(IDS_CANCEL_RIP),
  325. WASABI_API_LNGSTRINGW_BUF(IDS_CD_RIP_QUESTION,title,64),
  326. MB_YESNO | MB_ICONQUESTION) == IDYES)
  327. {
  328. if (m_rip_params) LockCD(m_rip_params->drive_letter, FALSE);
  329. if (m_extract_wnd) DestroyWindow(m_extract_wnd);
  330. DestroyWindow(hwndDlg);
  331. }
  332. return 0;
  333. }
  334. case IDC_BTN_SHOWINFO:
  335. switch(HIWORD(wParam))
  336. {
  337. case BN_CLICKED:
  338. SendMessageW(GetParent(hwndDlg), WM_COMMAND, wParam, lParam);
  339. NotifyInfoWindow(hwndDlg, TRUE);
  340. break;
  341. }
  342. break;
  343. }
  344. break;
  345. case WM_DESTROY:
  346. if (m_statuslist.getwnd())
  347. {
  348. g_view_metaconf->WriteInt(L"col_track", m_statuslist.GetColumnWidth(0));
  349. g_view_metaconf->WriteInt(L"col_title", m_statuslist.GetColumnWidth(1));
  350. g_view_metaconf->WriteInt(L"col_len", m_statuslist.GetColumnWidth(2));
  351. g_view_metaconf->WriteInt(L"col_status", m_statuslist.GetColumnWidth(3));
  352. }
  353. m_hwndstatus = 0;
  354. return 0;
  355. case WM_ERASEBKGND: return 1; //handled by WADlg_DrawChildWindowBorders in WM_PAINT
  356. case WM_QUERYFILEINFO: Window_OnQueryInfo(hwndDlg); break;
  357. case WM_NOTIFY: return Window_OnNotify(hwndDlg, (INT)wParam, (LPNMHDR) lParam);
  358. }
  359. return 0;
  360. }
  361. static BOOL CALLBACK extract_dialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  362. {
  363. switch (uMsg)
  364. {
  365. case WM_INITDIALOG:
  366. m_extract_wnd = hwndDlg;
  367. m_rip_done = 0;
  368. SetDlgItemText(hwndDlg, IDC_STATUS, WASABI_API_LNGSTRINGW(IDS_INITIALIZING));
  369. m_pstat_bytesdone = 0;
  370. m_pstat_bytesout = 0;
  371. m_pstat_timedone = 0;
  372. m_extract_nb = 0;
  373. m_extract_curtrack = -1;
  374. m_cur_rg = 0;
  375. {
  376. m_extract_nb_total = 0;
  377. int l = m_rip_params->ntracks;
  378. for (int i = 0;i < l;i++) if (m_rip_params->tracks[i]) m_extract_nb_total++;
  379. }
  380. LockCD(m_rip_params->drive_letter, TRUE);
  381. SetPropW(hwndDlg, L"WARIPPER", (HANDLE)hwndDlg);
  382. SetPropW(hwndDlg, L"DRIVE", (HANDLE)(INT_PTR)(0xFF & m_rip_params->drive_letter));
  383. if (!uMsgRipperNotify) uMsgRipperNotify = RegisterWindowMessageA("WARIPPER_BROADCAST_MSG");
  384. if (uMsgRipperNotify) SendNotifyMessage(HWND_BROADCAST, uMsgRipperNotify, (WPARAM)m_rip_params->drive_letter, (LPARAM)TRUE);
  385. SendDlgItemMessage(hwndDlg, IDC_PROGRESS1, PBM_SETRANGE, 0, MAKELPARAM(0, 100));
  386. SendDlgItemMessage(hwndDlg, IDC_PROGRESS2, PBM_SETRANGE, 0, MAKELPARAM(0, 100));
  387. PostMessage(hwndDlg, WM_APP + 1, 0, 0);
  388. if (g_config->ReadInt(L"cdripstatuswnd", 0)) ShowWindow(hwndDlg, SW_SHOW);
  389. INT bVal;
  390. if (S_OK == Settings_GetBool(C_EXTRACT, EF_CALCULATERG, &bVal) && bVal)
  391. {
  392. CreateGain();
  393. QueueUserAPC(StartGain, rgThread,
  394. (ULONG_PTR)((m_rip_params->ntracks == m_extract_nb_total) ? RG_ALBUM : RG_INDIVIDUAL_TRACKS));
  395. }
  396. break;
  397. case WM_APP + 2: // track is starting to be RG scanned
  398. m_statuslist.SetItemText(m_cur_rg, 3, WASABI_API_LNGSTRINGW(IDS_CALCULATING_REPLAY_GAIN));
  399. break;
  400. case WM_APP + 3: // track is starting to be RG scanned
  401. m_statuslist.SetItemText(m_cur_rg, 3, WASABI_API_LNGSTRINGW(IDS_COMPLETED));
  402. m_cur_rg++;
  403. break;
  404. case WM_APP + 1:
  405. {
  406. INT trackOffset, cchDest;
  407. TCHAR szDestination[MAX_PATH] = {0}, szFormat[MAX_PATH] = {0};
  408. int l = m_rip_params->ntracks;
  409. done = 1;
  410. Settings_GetInt(C_EXTRACT, EF_TRACKOFFSET, &trackOffset);
  411. Settings_ReadString(C_EXTRACT, EF_TITLEFMT, szFormat, ARRAYSIZE(szFormat));
  412. Settings_ReadString(C_EXTRACT, EF_PATH, szDestination, ARRAYSIZE(szDestination));
  413. CleanupDirectoryString(szDestination);
  414. cchDest = lstrlen(szDestination);
  415. for (int i = m_extract_curtrack + 1;i < l;i++)
  416. {
  417. if (m_rip_params->tracks[i])
  418. {
  419. StringCchPrintfW(m_extract_src, 64, L"cda://%c,%d.cda", m_rip_params->drive_letter, i + 1);
  420. szDestination[cchDest] = TEXT('\0');
  421. if (cchDest) PathAddBackslash(szDestination);
  422. wchar_t tmp1[32] = {0}, tmp2[32] = {0}, tmp3[32] = {0}, tmp4[32] = {0}, tmp5[32] = {0};
  423. FormatFileName(szDestination,
  424. ARRAYSIZE(szDestination)-11, // ensure we're leaving enough room for the extension
  425. szFormat,
  426. i + trackOffset,
  427. (m_rip_params->artist && *(m_rip_params->artist)) ? (m_rip_params->artist) : WASABI_API_LNGSTRINGW_BUF(IDS_UNKNOWN_ARTIST,tmp1,32),
  428. (m_rip_params->album && *(m_rip_params->album)) ? (m_rip_params->album) : WASABI_API_LNGSTRINGW_BUF(IDS_UNKNOWN_ALBUM,tmp2,32),
  429. (m_rip_params->tracks[i] && *(m_rip_params->tracks[i])) ? (m_rip_params->tracks[i]) : L"0",
  430. (m_rip_params->genre && *(m_rip_params->genre)) ? (m_rip_params->genre) : WASABI_API_LNGSTRINGW_BUF(IDS_UNKNOWN,tmp3,32),
  431. (m_rip_params->year && *(m_rip_params->year)) ? (m_rip_params->year) : WASABI_API_LNGSTRINGW_BUF(IDS_UNKNOWN,tmp4,32),
  432. (m_rip_params->trackArtists[i] && m_rip_params->trackArtists[i][0])?m_rip_params->trackArtists[i] : WASABI_API_LNGSTRINGW_BUF(IDS_UNKNOWN,tmp5,32),
  433. NULL, (m_rip_params->disc && *(m_rip_params->disc)) ? (m_rip_params->disc) : L"");
  434. memset(&m_fcs, 0, sizeof(m_fcs));
  435. m_fcs.sourcefile = m_extract_src;
  436. INT fourcc;
  437. Settings_GetInt(C_EXTRACT, EF_FOURCC, &fourcc);
  438. m_fcs.destformat[0]=fourcc;
  439. if (m_fcs.destformat[0] == OLD_AAC_CODEC) Settings_GetDefault(C_EXTRACT, EF_FOURCC, &m_fcs.destformat[0]);
  440. // now determine the extension
  441. wchar_t fmt[10] = {0};
  442. GetExtensionString(fmt, ARRAYSIZE(fmt), (DWORD)m_fcs.destformat[0]);
  443. BOOL upperCase;
  444. if (SUCCEEDED(Settings_GetBool(C_EXTRACT, EF_UPPEREXTENSION, &upperCase)) && FALSE != upperCase)
  445. CharUpper(fmt);
  446. else
  447. CharLower(fmt);
  448. StringCchCat(szDestination, ARRAYSIZE(szDestination), TEXT("."));
  449. StringCchCat(szDestination, ARRAYSIZE(szDestination), fmt);
  450. if (m_rip_params->filenames[i]) free(m_rip_params->filenames[i]);
  451. m_rip_params->filenames[i] = _wcsdup(szDestination);
  452. wchar_t tempFile[MAX_PATH] = {0};
  453. wchar_t tmppath[MAX_PATH] = {0};
  454. GetTempPath(MAX_PATH,tmppath);
  455. GetTempFileName(tmppath,L"rip",0,tempFile);
  456. m_rip_params->tempFilenames[i] = _wcsdup(tempFile);
  457. createDirForFileW(m_rip_params->filenames[i]);
  458. m_fcs.destfile = _wcsdup(tempFile);
  459. createDirForFileW(m_fcs.destfile);
  460. m_fcs.callbackhwnd = hwndDlg;
  461. m_fcs.error = L"";
  462. m_extract_time = 0;
  463. m_extract_curtrack = i;
  464. wchar_t *ptr = m_rip_params->filenames[i];
  465. if (cchDest && cchDest < (int)lstrlenW(ptr)) ptr += (cchDest + 1);
  466. SetDlgItemText(hwndDlg, IDC_CURTRACK, ptr);
  467. if (SendMessage(plugin.hwndWinampParent, WM_WA_IPC, (WPARAM)&m_fcs, IPC_CONVERTFILEW) != 1)
  468. {
  469. wchar_t tmp[512] = {0};
  470. StringCchPrintf(tmp, 512, WASABI_API_LNGSTRINGW(IDS_ERROR_RIPPING_TRACK), i + 1, m_fcs.error ? m_fcs.error : L"");
  471. MessageBox(hwndDlg, tmp, WASABI_API_LNGSTRINGW(IDS_ERROR), MB_OK);
  472. done = -1;
  473. break;
  474. }
  475. convertSetPriorityW csp = {
  476. &m_fcs,
  477. g_config->ReadInt(L"extractprio", THREAD_PRIORITY_NORMAL),
  478. };
  479. SendMessage(plugin.hwndWinampParent, WM_WA_IPC, (WPARAM)&csp, IPC_CONVERT_SET_PRIORITYW);
  480. m_extracting = 1;
  481. done = 0;
  482. PostMessage(hwndDlg, WM_WA_IPC , 0, IPC_CB_CONVERT_STATUS);
  483. break;
  484. }
  485. }
  486. if (done && m_rip_params)
  487. {
  488. LockCD(m_rip_params->drive_letter, FALSE);
  489. if (g_config->ReadInt(L"cdripautoeject", 0) && done > 0)
  490. {
  491. char buf[64] = {0};
  492. StringCchPrintfA(buf, 64, "cda://%c.cda", m_rip_params->drive_letter);
  493. char buf2[32] = {0};
  494. getFileInfo(buf, "<eject>", buf2, sizeof(buf2));
  495. }
  496. if (g_config->ReadInt(L"cdripautoplay", 0) && done > 0)
  497. {
  498. SendMessage(plugin.hwndWinampParent, WM_WA_IPC, 0, IPC_DELETE);
  499. for (int i = 0;i < m_rip_params->ntracks;i++)
  500. {
  501. if (m_rip_params->tracks[i])
  502. {
  503. COPYDATASTRUCT cds;
  504. cds.dwData = IPC_PLAYFILEW;
  505. cds.lpData = (void *) m_rip_params->filenames[i];
  506. cds.cbData = sizeof(wchar_t) * (lstrlenW(m_rip_params->filenames[i]) + 1); // include space for null char
  507. SendMessage(plugin.hwndWinampParent, WM_COPYDATA, (WPARAM)NULL, (LPARAM)&cds);
  508. }
  509. }
  510. SendMessage(plugin.hwndWinampParent, WM_WA_IPC, 0, IPC_STARTPLAY);
  511. }
  512. if (m_rip_params->ntracks == m_extract_nb_total && done > 0)
  513. {
  514. INT bVal;
  515. if ((S_OK == Settings_GetBool(C_EXTRACT, EF_CREATEM3U, &bVal) && bVal) ||
  516. (S_OK == Settings_GetBool(C_EXTRACT, EF_CREATEPLS, &bVal) && bVal))
  517. {
  518. wchar_t str[MAX_PATH] = {0}, fmt[MAX_PATH] = {0};
  519. Settings_ReadString(C_EXTRACT, EF_PLAYLISTFMT, fmt, ARRAYSIZE(fmt));
  520. Settings_ReadString(C_EXTRACT, EF_PATH, str, ARRAYSIZE(str));
  521. int l = lstrlenW(str);
  522. if (l)
  523. PathAddBackslash(str);
  524. FormatFileName(str, ARRAYSIZE(str)-5, // ensure we're leaving enough room for the extension
  525. fmt, 0xdeadbeef,
  526. m_rip_params->artist ? m_rip_params->artist : L"",
  527. m_rip_params->album ? m_rip_params->album : L"",
  528. NULL,
  529. m_rip_params->genre ? m_rip_params->genre : L"",
  530. m_rip_params->year ? m_rip_params->year : L"",
  531. NULL,
  532. NULL,
  533. m_rip_params->disc ? m_rip_params->disc : L"");
  534. if (S_OK == Settings_GetBool(C_EXTRACT, EF_CREATEM3U, &bVal) && bVal)
  535. {
  536. wchar_t str2[MAX_PATH] = {0};
  537. lstrcpynW(str2, str, MAX_PATH);
  538. StringCchCatW(str2, MAX_PATH, L".m3u");
  539. createDirForFileW(str2);
  540. M3UWriter w;
  541. FILE *fp=_wfopen(str2, L"wt");
  542. w.Open(fp, AutoCharFn(str2), TRUE);
  543. BOOL ext;
  544. Settings_GetBool(C_EXTRACT, EF_USEM3UEXT, &ext);
  545. for (int i = 0;i < m_rip_params->ntracks;i++)
  546. {
  547. if (m_rip_params->tracks[i] && m_rip_params->filenames[i])
  548. {
  549. GayString str;
  550. str.Set(AutoChar(m_rip_params->artist));
  551. str.Append(" - ");
  552. str.Append(AutoChar(m_rip_params->tracks[i]));
  553. if (ext)
  554. w.SetExtended(AutoCharFn(m_rip_params->filenames[i]), str.Get(), m_rip_params->lengths[i]);
  555. else
  556. w.SetFilename(AutoCharFn(m_rip_params->filenames[i]));
  557. }
  558. }
  559. w.Close();
  560. }
  561. if (S_OK == Settings_GetBool(C_EXTRACT, EF_CREATEPLS, &bVal) && bVal)
  562. {
  563. char str2[MAX_PATH] = {0};
  564. lstrcpynA(str2, AutoChar(str), MAX_PATH);
  565. StringCchCatA(str2, MAX_PATH, ".pls");
  566. createDirForFile(str2);
  567. // TODO: check for bad unicode conversion
  568. PLSWriter w;
  569. w.Open(str2);
  570. for (int i = 0;i < m_rip_params->ntracks;i++)
  571. {
  572. if (m_rip_params->tracks[i] && m_rip_params->filenames[i])
  573. {
  574. GayString str;
  575. str.Set(AutoChar(m_rip_params->artist));
  576. str.Append(" - ");
  577. str.Append(AutoChar(m_rip_params->tracks[i]));
  578. w.SetFilename(AutoCharFn(m_rip_params->filenames[i]));
  579. w.SetTitle(str.Get());
  580. w.SetLength(m_rip_params->lengths[i]);
  581. w.Next();
  582. }
  583. }
  584. w.Close();
  585. }
  586. }
  587. if (S_OK == Settings_GetBool(C_EXTRACT, EF_CREATEMLPL, &bVal) && bVal)
  588. {
  589. itemRecordListW irl = {0, };
  590. allocRecordList(&irl, m_rip_params->ntracks, 0);
  591. for (int i = 0;i < m_rip_params->ntracks;i++)
  592. {
  593. if (m_rip_params->tracks[i])
  594. {
  595. int n = irl.Size;
  596. memset(&irl.Items[n], 0, sizeof(itemRecordW));
  597. irl.Items[n].filename = _wcsdup(m_rip_params->filenames[i]);
  598. irl.Items[n].album = _wcsdup(m_rip_params->album);
  599. irl.Items[n].artist = _wcsdup(m_rip_params->artist);
  600. irl.Items[n].title = _wcsdup(m_rip_params->tracks[i]);
  601. irl.Items[n].genre = _wcsdup(m_rip_params->genre);
  602. irl.Items[n].year = _wtoi(m_rip_params->year);
  603. irl.Items[n].length = m_rip_params->lengths[i];
  604. irl.Size++;
  605. }
  606. }
  607. GayString str;
  608. str.Set(AutoChar(m_rip_params->artist));
  609. str.Append(" - ");
  610. str.Append(AutoChar(m_rip_params->album));
  611. AutoWide name(str.Get());
  612. mlMakePlaylist pl = {sizeof(mlMakePlaylist), (const wchar_t*)name, ML_TYPE_ITEMRECORDLISTW, (void *) & irl, 0x01};
  613. SendMessage(plugin.hwndLibraryParent, WM_ML_IPC, (WPARAM)&pl, ML_IPC_PLAYLIST_MAKE);
  614. freeRecordList(&irl);
  615. }
  616. } // playlist creation
  617. if (rgThread)
  618. QueueUserAPC(WriteGain, rgThread, 0);
  619. else
  620. PostMessage(m_extract_wnd, WM_APP + 4, 0, 0);
  621. }
  622. }
  623. break;
  624. case WM_APP + 4:
  625. if (m_db_has_upd)
  626. {
  627. // TODO: benski> does mldb read metadata from this call or the 'add' call - because it won't have replaygain tags until now
  628. PostMessage(plugin.hwndLibraryParent, WM_ML_IPC, 0, ML_IPC_DB_SYNCDB);
  629. }
  630. m_rip_done = 1;
  631. if (g_config->ReadInt(L"cdripautoclose", 1))
  632. {
  633. DestroyWindow(hwndDlg);
  634. }
  635. else
  636. {
  637. SetWindowText(hwndDlg, WASABI_API_LNGSTRINGW(done > 0 ? IDS_RIP_COMPLETE : IDS_RIP_FAILED));
  638. SetDlgItemText(hwndDlg, IDC_BUTTON1, WASABI_API_LNGSTRINGW(IDS_CLOSE));
  639. if (m_hwndstatus)
  640. {
  641. SetDlgItemText(m_hwndstatus, IDC_CANCEL_RIP, WASABI_API_LNGSTRINGW(IDS_CLOSE));
  642. }
  643. SendDlgItemMessage(hwndDlg, IDC_PROGRESS1, PBM_SETPOS, 100, 0);
  644. SendDlgItemMessage(hwndDlg, IDC_PROGRESS2, PBM_SETPOS, 100, 0);
  645. int now = m_pstat_timedone;
  646. int bytesout = m_pstat_bytesout;
  647. double extracted_time = (double) m_pstat_bytesdone * (1.0 / 44100.0 / 4.0);
  648. if (extracted_time < 1.0) extracted_time = 1.0;
  649. int br = (int) (((double)bytesout * 8.0 / extracted_time) / 1000.0 + 0.5);
  650. if (done > 0)
  651. {
  652. wchar_t sstr[16] = {0};
  653. StringCchPrintf(m_last_total_status, 512,
  654. WASABI_API_LNGSTRINGW(IDS_X_TRACKS_RIPPED_IN_X),
  655. m_extract_nb_total,
  656. WASABI_API_LNGSTRINGW_BUF(m_extract_nb_total == 1 ? IDS_TRACK : IDS_TRACKS,sstr,16),
  657. now / 1000 / 60, (now / 1000) % 60,
  658. extracted_time / (now / 1000.0),
  659. br, (double)bytesout * (1.0 / (1024.0*1024.0))
  660. );
  661. }
  662. else
  663. {
  664. WASABI_API_LNGSTRINGW_BUF(IDS_RIP_FAILED,m_last_total_status,512);
  665. }
  666. SetDlgItemText(hwndDlg, IDC_STATUS2, m_last_total_status);
  667. SetDlgItemText(hwndDlg, IDC_CURTRACK, WASABI_API_LNGSTRINGW(IDS_COMPLETED));
  668. SetDlgItemText(hwndDlg, IDC_STATUS, L"");
  669. if (m_hwndstatus && IsWindow(m_hwndstatus))
  670. {
  671. SetDlgItemText(m_hwndstatus, IDC_CDINFO, m_last_total_status);
  672. SetDlgItemText(m_hwndstatus, IDC_CANCEL_RIP, WASABI_API_LNGSTRINGW(IDS_DONE));
  673. }
  674. }
  675. break;
  676. case WM_WA_IPC:
  677. switch (lParam)
  678. {
  679. case IPC_CB_CONVERT_STATUS:
  680. {
  681. if (!m_extract_time)
  682. {
  683. m_extract_time = GetTickCount();
  684. break;
  685. }
  686. DWORD now = GetTickCount() - m_extract_time;
  687. if (!now) now = 1000; //safety
  688. wchar_t tmp[512 + 128] = {0};
  689. {
  690. int total_t = 0;
  691. if (wParam) total_t = MulDiv(100, now, (int)wParam);
  692. int rem_t = total_t - now;
  693. double extracted_time = (double) m_fcs.bytes_done * (1.0 / 44100.0 / 4.0);
  694. if (extracted_time < 1.0) extracted_time = 1.0;
  695. int br = (int) (((double)m_fcs.bytes_out * 8.0 / extracted_time) / 1000.0 + 0.5);
  696. int estsize = 0;
  697. if (m_fcs.bytes_total > 0) estsize = MulDiv(m_fcs.bytes_out, m_fcs.bytes_total, m_fcs.bytes_done);
  698. if (rem_t < 0) rem_t = 0;
  699. if (total_t < 0) total_t = 0;
  700. StringCchPrintf(tmp, 640,
  701. WASABI_API_LNGSTRINGW(IDS_ELAPSED_X_REMAINING_X_TOTAL_X),
  702. now / 1000 / 60, (now / 1000) % 60,
  703. rem_t / 1000 / 60, (rem_t / 1000) % 60,
  704. total_t / 1000 / 60, (total_t / 1000) % 60,
  705. extracted_time / ((double)now / 1000.0),
  706. br, (double)estsize * (1.0 / (1024.0*1024.0))
  707. );
  708. SetDlgItemText(hwndDlg, IDC_STATUS, tmp);
  709. if (m_hwndstatus && IsWindow(m_hwndstatus))
  710. {
  711. StringCchPrintf(m_last_item_status, 512,
  712. WASABI_API_LNGSTRINGW(IDS_X_KBPS_AT_X_REALTIME),
  713. wParam,
  714. br,
  715. extracted_time / ((double)now / 1000.0)
  716. );
  717. m_statuslist.SetItemText(m_extract_nb, 3, m_last_item_status);
  718. }
  719. }
  720. {
  721. int total_in_bytes_calc = m_rip_params->total_length_bytes;
  722. now += m_pstat_timedone;
  723. int total_t = 0;
  724. int bytesdone = m_fcs.bytes_done + m_pstat_bytesdone;
  725. int bytesout = m_fcs.bytes_out + m_pstat_bytesout;
  726. if (bytesdone) total_t = MulDiv(total_in_bytes_calc, now, bytesdone);
  727. int rem_t = total_t - now;
  728. double extracted_time = (double) bytesdone * (1.0 / 44100.0 / 4.0);
  729. if (extracted_time < 1.0) extracted_time = 1.0;
  730. int br = (int) (((double)bytesout * 8.0 / extracted_time) / 1000.0 + 0.5);
  731. int estsize = 0;
  732. if (total_in_bytes_calc > 0) estsize = MulDiv(bytesout, total_in_bytes_calc, bytesdone);
  733. if (rem_t < 0) rem_t = 0;
  734. if (total_t < 0) total_t = 0;
  735. StringCchPrintf(m_last_total_status, 512,
  736. WASABI_API_LNGSTRINGW(IDS_X_OF_X_ELAPSED_X_REMAINING_X),
  737. m_extract_nb + 1, m_extract_nb_total,
  738. now / 1000 / 60, (now / 1000) % 60,
  739. rem_t / 1000 / 60, (rem_t / 1000) % 60,
  740. total_t / 1000 / 60, (total_t / 1000) % 60,
  741. extracted_time / ((double)now / 1000.0),
  742. br, (double)estsize * (1.0 / (1024.0*1024.0))
  743. );
  744. if (m_hwndstatus && IsWindow(m_hwndstatus))
  745. {
  746. SetDlgItemText(m_hwndstatus, IDC_CDINFO, m_last_total_status);
  747. }
  748. SetDlgItemText(hwndDlg, IDC_STATUS2, m_last_total_status);
  749. int a = 0;
  750. if (total_in_bytes_calc) a = MulDiv(bytesdone, 100, total_in_bytes_calc);
  751. SendDlgItemMessage(hwndDlg, IDC_PROGRESS2, PBM_SETPOS, a, 0);
  752. StringCchPrintf(tmp, 640, WASABI_API_LNGSTRINGW(IDS_X_PERCENT_RIPPING_FROM_CD), a);
  753. SetWindowText(hwndDlg, tmp);
  754. }
  755. SendDlgItemMessage(hwndDlg, IDC_PROGRESS1, PBM_SETPOS, wParam, 0);
  756. }
  757. break;
  758. case IPC_CB_CONVERT_DONE:
  759. SendMessage(plugin.hwndWinampParent , WM_WA_IPC, (WPARAM)&m_fcs, IPC_CONVERTFILEW_END);
  760. free(m_fcs.destfile);
  761. m_pstat_bytesdone += m_fcs.bytes_done;
  762. m_pstat_bytesout += m_fcs.bytes_out;
  763. if (m_extract_time) m_pstat_timedone += GetTickCount() - m_extract_time;
  764. CopyFileW(m_rip_params->tempFilenames[m_extract_curtrack], m_rip_params->filenames[m_extract_curtrack], FALSE);
  765. DeleteFileW(m_rip_params->tempFilenames[m_extract_curtrack]);
  766. if (AGAVE_API_STATS)
  767. {
  768. AGAVE_API_STATS->IncrementStat(api_stats::RIP_COUNT);
  769. AGAVE_API_STATS->SetStat(api_stats::RIP_FORMAT, m_fcs.destformat[0]);
  770. }
  771. wchar_t *lastfn = m_rip_params->filenames[m_extract_curtrack];
  772. if (g_config->ReadInt(L"extracttag", 1))
  773. {
  774. // add metadata to this file
  775. if (updateFileInfoW(lastfn, L"title", m_rip_params->tracks[m_extract_curtrack]))
  776. {
  777. updateFileInfoW(lastfn, L"conductor", m_rip_params->conductors[m_extract_curtrack]);
  778. updateFileInfoW(lastfn, L"composer", m_rip_params->composers[m_extract_curtrack]);
  779. updateFileInfoW(lastfn, L"GracenoteFileID", m_rip_params->gracenoteFileIDs[m_extract_curtrack]);
  780. updateFileInfoW(lastfn, L"GracenoteExtData", m_rip_params->gracenoteExtData[m_extract_curtrack]);
  781. updateFileInfoW(lastfn, L"artist", m_rip_params->trackArtists[m_extract_curtrack]);
  782. //if (lstrcmpiW(m_rip_params->trackArtists[m_extract_curtrack], m_rip_params->artist)) // only write albumartist if they're different
  783. updateFileInfoW(lastfn, L"albumartist", m_rip_params->artist);
  784. updateFileInfoW(lastfn, L"album", m_rip_params->album);
  785. updateFileInfoW(lastfn, L"genre", m_rip_params->genre);
  786. updateFileInfoW(lastfn, L"year", m_rip_params->year);
  787. updateFileInfoW(lastfn, L"disc", m_rip_params->disc);
  788. updateFileInfoW(lastfn, L"publisher", m_rip_params->publisher);
  789. if (m_rip_params->comment && m_rip_params->comment[0])
  790. updateFileInfoW(lastfn, L"comment", m_rip_params->comment);
  791. else
  792. {
  793. TCHAR szComment[8192] = {0};
  794. Settings_ReadString(C_EXTRACT, EF_COMMENTTEXT, szComment, ARRAYSIZE(szComment));
  795. updateFileInfoW(lastfn, L"comment", szComment);
  796. }
  797. wchar_t buf[32] = {0};
  798. if (m_extract_curtrack >= 0)
  799. {
  800. if (g_config->ReadInt(L"total_tracks", 0))
  801. StringCchPrintfW(buf, 32, L"%d/%d", m_extract_curtrack + g_config->ReadInt(L"trackoffs", 1), m_rip_params->ntracks);
  802. else
  803. StringCchPrintfW(buf, 32, L"%d", m_extract_curtrack + g_config->ReadInt(L"trackoffs", 1));
  804. }
  805. else buf[0] = 0;
  806. updateFileInfoW(lastfn, L"track", buf);
  807. if (WASABI_API_APP)
  808. updateFileInfoW(lastfn, L"tool", WASABI_API_APP->main_getVersionString());
  809. SendMessage(plugin.hwndWinampParent, WM_WA_IPC, 0, IPC_WRITE_EXTENDED_FILE_INFO);
  810. }
  811. }
  812. if (g_config->ReadInt(L"extractaddml", 1))
  813. {
  814. LMDB_FILE_ADD_INFOW fi = {lastfn, -1, -1};
  815. SENDMLIPC(plugin.hwndLibraryParent, ML_IPC_DB_ADDORUPDATEFILEW, (WPARAM)&fi);
  816. m_db_has_upd = 1;
  817. }
  818. if (m_hwndstatus && IsWindow(m_hwndstatus))
  819. {
  820. m_statuslist.SetItemText(m_extract_nb, 3, WASABI_API_LNGSTRING(IDS_WAITING));
  821. }
  822. if (rgThread)
  823. QueueUserAPC(CalculateGain, rgThread, (ULONG_PTR)_wcsdup(lastfn));
  824. else
  825. PostMessage(m_extract_wnd, WM_APP + 3, 0, 0);
  826. m_extract_nb++;
  827. m_extracting = 0;
  828. PostMessage(hwndDlg, WM_APP + 1, 0, 0);
  829. break;
  830. }
  831. break;
  832. case WM_COMMAND:
  833. switch (LOWORD(wParam))
  834. {
  835. case IDC_BUTTON1:
  836. {
  837. wchar_t title[64] = {0};
  838. if (m_rip_done ||
  839. MessageBox(hwndDlg, WASABI_API_LNGSTRINGW(IDS_CANCEL_RIP),
  840. WASABI_API_LNGSTRINGW_BUF(IDS_CD_RIP_QUESTION,title,64),
  841. MB_YESNO | MB_ICONQUESTION) == IDYES)
  842. {
  843. LockCD(m_rip_params->drive_letter, FALSE);
  844. DestroyWindow(hwndDlg);
  845. }
  846. return 0;
  847. }
  848. case IDCANCEL:
  849. g_config->WriteInt(L"cdripstatuswnd", 0);
  850. ShowWindow(hwndDlg, SW_HIDE);
  851. break;
  852. }
  853. break;
  854. case WM_CLOSE:
  855. return 0;
  856. case WM_DESTROY:
  857. if (m_extracting)
  858. {
  859. SendMessage(plugin.hwndWinampParent, WM_WA_IPC, (WPARAM)&m_fcs, IPC_CONVERTFILEW_END);
  860. // make sure we clean up on cancel!
  861. m_extracting = 0;
  862. DeleteFileW(m_rip_params->tempFilenames[m_extract_curtrack]);
  863. }
  864. if (uMsgRipperNotify) SendNotifyMessage(HWND_BROADCAST, uMsgRipperNotify, (WPARAM)(m_rip_params) ? m_rip_params->drive_letter : 0, (LPARAM)FALSE);
  865. if (m_rip_params)
  866. {
  867. int i;
  868. for (i = 0; i < m_rip_params->ntracks; i++)
  869. {
  870. free(m_rip_params->tracks[i]);
  871. free(m_rip_params->trackArtists[i]);
  872. free(m_rip_params->composers[i]);
  873. free(m_rip_params->gracenoteFileIDs[i]);
  874. free(m_rip_params->gracenoteExtData[i]);
  875. free(m_rip_params->conductors[i]);
  876. free(m_rip_params->filenames[i]);
  877. free(m_rip_params->tempFilenames[i]);
  878. }
  879. free(m_rip_params->gracenoteFileIDs);
  880. free(m_rip_params->gracenoteExtData);
  881. free(m_rip_params->composers);
  882. free(m_rip_params->conductors);
  883. free(m_rip_params->tracks);
  884. free(m_rip_params->trackArtists);
  885. free(m_rip_params->filenames);
  886. free(m_rip_params->tempFilenames);
  887. free(m_rip_params->lengths);
  888. free(m_rip_params->album);
  889. free(m_rip_params->artist);
  890. free(m_rip_params->genre);
  891. free(m_rip_params->year);
  892. free(m_rip_params->publisher);
  893. free(m_rip_params->comment);
  894. free(m_rip_params->disc);
  895. free(m_rip_params);
  896. m_rip_params = 0;
  897. }
  898. m_extract_wnd = 0;
  899. if (rgThread)
  900. QueueUserAPC(CloseGain, rgThread, 0);
  901. break;
  902. }
  903. return 0;
  904. }
  905. void cdrip_stop_all_extracts()
  906. {
  907. if (m_rip_params) LockCD(m_rip_params->drive_letter, FALSE);
  908. if (m_extract_wnd) DestroyWindow(m_extract_wnd);
  909. if (m_hwndstatus) DestroyWindow(m_hwndstatus);
  910. }
  911. int cdrip_isextracting(char drive)
  912. {
  913. if (!m_rip_params) return 0;
  914. if (drive == -1 && m_rip_done)
  915. {
  916. if (m_extract_wnd && IsWindow(m_extract_wnd)) DestroyWindow(m_extract_wnd);
  917. if (m_hwndstatus && IsWindow(m_hwndstatus)) DestroyWindow(m_hwndstatus);
  918. return 0;
  919. }
  920. if (drive == 0 || drive == -1) return toupper(m_rip_params->drive_letter);
  921. return toupper(m_rip_params->drive_letter) == toupper(drive);
  922. }
  923. HWND cdrip_FindBurningHWND(char cLetter)
  924. {
  925. HWND h = 0;
  926. while (NULL != (h = FindWindowExW(NULL, h, L"#32770", NULL)))
  927. {
  928. if (!GetPropW(h, L"WARIPPER")) continue;
  929. if (((char)(INT_PTR)GetPropW(h, L"DRIVE")) == cLetter) return h;
  930. }
  931. return NULL;
  932. }
  933. void cdrip_extractFiles(cdrip_params *parms)
  934. {
  935. WASABI_API_LNGSTRINGW_BUF(IDS_INITIALIZING,m_last_total_status,512);
  936. m_last_item_status[0] = 0;
  937. m_rip_params = parms;
  938. WASABI_API_CREATEDIALOGW(IDD_VIEW_CDROM_EXTRACT, plugin.hwndWinampParent, extract_dialogProc);
  939. }