cdburn.cpp 64 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155
  1. #include "main.h"
  2. #include <stdio.h>
  3. #include "../nu/ns_wc.h"
  4. #include "resource.h"
  5. #include "../nu/listview.h"
  6. #include "../nu/DialogSkinner.h"
  7. #include "../nu/ChildSizer.h"
  8. #include "config.h"
  9. #include "../../General/gen_ml/gaystring.h"
  10. #include "../Winamp/burn.h"
  11. #include "../Winamp/strutil.h"
  12. #include <std::vector>
  13. #include "../nu/AutoChar.h"
  14. #include "../nu/AutoWide.h"
  15. #include <api/service/waServiceFactory.h>
  16. #include "../playlist/ifc_playlistloadercallback.h"
  17. #include "../playlist/api_playlistmanager.h"
  18. #include <imapi.h>
  19. #include <imapierror.h>
  20. #include <shlwapi.h>
  21. #include <strsafe.h>
  22. //shit to finish:
  23. //-erase CDRWs
  24. //-cache the veritas handle
  25. //-recurse add folders
  26. //-check for available space on HD before burning
  27. //-the resampling in convert
  28. #define WM_EX_OPCOMPLETED (WM_USER + 0x100)
  29. class PLCallBack : ifc_playlistloadercallback
  30. {
  31. public:
  32. PLCallBack(void) : fileList(0) {};
  33. ~PLCallBack(void) {};
  34. public:
  35. void OnFile(const wchar_t *filename, const wchar_t *title, int lengthInMS, ifc_plentryinfo *info)
  36. {
  37. fileList->push_back(new GayString(AutoChar(filename)));
  38. }
  39. RECVS_DISPATCH;
  40. public:
  41. std::vector<GayString*> *fileList;
  42. };
  43. #define CBCLASS PLCallBack
  44. START_DISPATCH;
  45. VCB(IFC_PLAYLISTLOADERCALLBACK_ONFILE, OnFile)
  46. END_DISPATCH;
  47. #undef CBCLASS
  48. class PLCallBackW : ifc_playlistloadercallback
  49. {
  50. public:
  51. PLCallBackW(void) : fileList(0) {};
  52. ~PLCallBackW(void) {};
  53. public:
  54. void OnFile(const wchar_t *filename, const wchar_t *title, int lengthInMS, ifc_plentryinfo *info)
  55. {
  56. fileList->push_back(new GayStringW(filename));
  57. }
  58. RECVS_DISPATCH;
  59. public:
  60. std::vector<GayStringW*> *fileList;
  61. };
  62. #define CBCLASS PLCallBackW
  63. START_DISPATCH;
  64. VCB(IFC_PLAYLISTLOADERCALLBACK_ONFILE, OnFile)
  65. END_DISPATCH;
  66. #undef CBCLASS
  67. static INT_PTR WINAPI DlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
  68. #include "../burnlib/burnlib.h"
  69. static W_ListView m_statuslist;
  70. static HWND m_hwndstatus;
  71. static char m_cdrom;
  72. static int m_is_cdrw, m_availsecs;
  73. static int m_max_speed;
  74. static int m_dragging, m_drag_item;
  75. static HWND prevWnd = NULL;
  76. itemRecordListW itemCache[100] = {0};
  77. static int percentCompleted = 0;
  78. static DWORD pidBurner = 0;
  79. static HFONT hPLFont = NULL;
  80. static int LETTERTOINDEX(char c)
  81. {
  82. c = (char)toupper(c);
  83. if (c < 'A') c = 'A';
  84. if (c > 'Z') c = 'Z';
  85. return c -'A';
  86. }
  87. #include "../winamp/wa_ipc.h"
  88. #define TIMER_NOTIFYINFO_ID 1985
  89. #define TIMER_NOTIFYINFO_DELAY 200
  90. static ChildWndResizeItem burnwnd_rlist[] =
  91. {
  92. {IDC_LIST2, 0x0011},
  93. {IDC_CDINFO, 0x0010},
  94. {IDC_ADD, 0x0101},
  95. {IDC_BURN, 0x0101},
  96. {IDC_CLEAR, 0x0101},
  97. {IDC_BURN_OPTS, 0x0101},
  98. {IDC_CANCEL_BURN, 0x0101},
  99. {IDC_LOGO, 0x1010},
  100. {IDC_BTN_SHOWINFO, 0x1111},
  101. };
  102. static _inline void code(long* v, long* k)
  103. {
  104. unsigned long y = v[0], z = v[1], sum = 0, /* set up */
  105. delta = 0x9e3779b9, n = 32 ; /* key schedule constant*/
  106. while (n-- > 0)
  107. { /* basic cycle start */
  108. sum += delta;
  109. y += ((z << 4) + k[0]) ^(z + sum) ^((z >> 5) + k[1]);
  110. z += ((y << 4) + k[2]) ^(y + sum) ^((y >> 5) + k[3]); /* end cycle */
  111. }
  112. v[0] = y; v[1] = z;
  113. }
  114. static void startBurn(HWND hwndDlg, char driveletter)
  115. {
  116. g_config->WriteInt(L"cdburnmaxspeed", m_max_speed);
  117. //write the temp playlist to disk
  118. FILE *fp;
  119. char filename[MAX_PATH] = {0}, tp[MAX_PATH] = {0};
  120. pidBurner = 0;
  121. if (!GetTempPathA(sizeof(tp), tp)) lstrcpynA(tp, ".", MAX_PATH);
  122. if (GetTempFileNameA(tp, "BRN", 0, filename))
  123. {
  124. unlink(filename);
  125. StringCchCatA(filename, MAX_PATH, ".m3u8");
  126. }
  127. else lstrcpynA(filename, "brn_tmp.m3u8", MAX_PATH);
  128. fp = fopen(filename, "wt");
  129. if (!fp)
  130. {
  131. wchar_t title[16] = {0};
  132. MessageBox(hwndDlg, WASABI_API_LNGSTRINGW(IDS_ERROR_WRITING_TEMP_BURN_LIST),
  133. WASABI_API_LNGSTRINGW_BUF(IDS_ERROR,title,16), MB_OK);
  134. return ;
  135. }
  136. int idx = LETTERTOINDEX(driveletter);
  137. fprintf(fp, "#EXTM3U\n");
  138. for (int i = 0;i < itemCache[idx].Size;i++)
  139. {
  140. fprintf(fp, "#EXTINF:%d,%s\n", itemCache[idx].Items[i].length, (char *)AutoChar(itemCache[idx].Items[i].title, CP_UTF8));
  141. fprintf(fp, "%s\n", (char *)AutoChar(itemCache[idx].Items[i].filename, CP_UTF8));
  142. }
  143. fclose(fp);
  144. burnCDStruct bcds =
  145. {
  146. m_cdrom,
  147. filename,
  148. hwndDlg,
  149. "",
  150. };
  151. pidBurner = (DWORD)(INT_PTR)SendMessage(plugin.hwndWinampParent, WM_WA_IPC, (WPARAM) & bcds, IPC_BURN_CD);
  152. if (!pidBurner)
  153. {
  154. wchar_t title[16] = {0};
  155. unlink(filename);
  156. MessageBox(hwndDlg, AutoWide(bcds.error), WASABI_API_LNGSTRINGW_BUF(IDS_ERROR,title,16), MB_OK);
  157. }
  158. }
  159. static void link_handledraw(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  160. {
  161. if (uMsg == WM_DRAWITEM)
  162. {
  163. DRAWITEMSTRUCT *di = (DRAWITEMSTRUCT *)lParam;
  164. if (di->CtlType == ODT_BUTTON)
  165. {
  166. wchar_t wt[123] = {0};
  167. int y;
  168. RECT r;
  169. HPEN hPen, hOldPen;
  170. GetDlgItemText(hwndDlg, (int)wParam, wt, 123);
  171. // draw text
  172. SetTextColor(di->hDC, (di->itemState & ODS_SELECTED) ? RGB(220, 0, 0) : RGB(0, 0, 220));
  173. r = di->rcItem;
  174. r.left += 2;
  175. DrawText(di->hDC, wt, -1, &r, DT_VCENTER | DT_SINGLELINE);
  176. memset(&r, 0, sizeof(r));
  177. DrawText(di->hDC, wt, -1, &r, DT_SINGLELINE | DT_CALCRECT);
  178. // draw underline
  179. y = di->rcItem.bottom - ((di->rcItem.bottom - di->rcItem.top) - (r.bottom - r.top)) / 2 - 1;
  180. hPen = CreatePen(PS_SOLID, 0, (di->itemState & ODS_SELECTED) ? RGB(220, 0, 0) : RGB(0, 0, 220));
  181. hOldPen = (HPEN) SelectObject(di->hDC, hPen);
  182. MoveToEx(di->hDC, di->rcItem.left + 2, y, NULL);
  183. LineTo(di->hDC, di->rcItem.right + 2 - ((di->rcItem.right - di->rcItem.left) - (r.right - r.left)), y);
  184. SelectObject(di->hDC, hOldPen);
  185. DeleteObject(hPen);
  186. }
  187. }
  188. }
  189. static void refreshList()
  190. {
  191. if (!m_hwndstatus) return ;
  192. ListView_SetItemCount(m_statuslist.getwnd(), 0);
  193. int idx = LETTERTOINDEX(m_cdrom);
  194. ListView_SetItemCount(m_statuslist.getwnd(), itemCache[idx].Size);
  195. if (itemCache[idx].Size > 0) ListView_RedrawItems(m_statuslist.getwnd(), 0, itemCache[idx].Size - 1);
  196. }
  197. static int m_last_trackpos;
  198. typedef struct _MEDIAINFO
  199. {
  200. CHAR cLetter;
  201. BOOL bInserted;
  202. BOOL bRecordable;
  203. BOOL bRewritable;
  204. BOOL bBlank;
  205. ULONG nSectorsFree;
  206. ULONG nSectorsUsed;
  207. } MEDIAINFO;
  208. static HRESULT GetMediaInfoFromSonic(MEDIAINFO *pmi)
  209. {
  210. HRESULT hr;
  211. hr = S_OK;
  212. char name[]= "cda://X.cda";
  213. char buf2[64] = "";
  214. char buf3[64] = "";
  215. name[6] = pmi->cLetter;
  216. pmi->bInserted = FALSE;
  217. pmi->bRewritable = FALSE;
  218. pmi->nSectorsFree = 0;
  219. pmi->nSectorsUsed = 0;
  220. pmi->bRecordable = TRUE;
  221. getFileInfo(name, "cdtype", buf3, sizeof(buf3));
  222. if (buf3[0] && 0 == lstrcmpA(buf3, "CDRW")) pmi->bRewritable = TRUE;
  223. getFileInfo(name, "cdlengths", buf2, sizeof(buf2));
  224. if (buf2[0])
  225. {
  226. pmi->bInserted = TRUE;
  227. pmi->nSectorsFree = atoi(buf2);
  228. }
  229. return hr;
  230. }
  231. static void CALLBACK FreeAsyncParam(DM_NOTIFY_PARAM *phdr)
  232. {
  233. switch(phdr->opCode)
  234. {
  235. case DMOP_IMAPIINFO:
  236. break;
  237. }
  238. free(phdr);
  239. }
  240. static void FinishSetStatus(HWND hwndDlg, MEDIAINFO *pmi)
  241. {
  242. int freesecs;
  243. if(pmi->bInserted)
  244. {
  245. freesecs = (pmi->nSectorsFree * 2048) / (150 * 1024); //150kb/s as its considered DATA CD at this point in veritas
  246. }
  247. else
  248. {
  249. freesecs = 74 * 60; //Default to 74mns CDR
  250. }
  251. m_availsecs = freesecs;
  252. int idx = LETTERTOINDEX(m_cdrom);
  253. int usedlen = 0;
  254. int truncpos = 0;
  255. for (int i = 0;i < itemCache[idx].Size;i++)
  256. {
  257. usedlen += itemCache[idx].Items[i].length;
  258. if (usedlen > m_availsecs)
  259. truncpos++;
  260. }
  261. m_availsecs -= usedlen;
  262. wchar_t status[256] = {0};
  263. if (!pmi->bInserted)
  264. WASABI_API_LNGSTRINGW_BUF(IDS_NO_BLANK_CDR_IN_DRIVE,status,512);
  265. else
  266. {
  267. StringCchPrintf(status, 512, WASABI_API_LNGSTRINGW(IDS_X_CAPACITY_DETAILS),
  268. (pmi->bRewritable) ? L"CD-RW" : L"CD-R" , freesecs / 60, freesecs % 60);
  269. }
  270. wchar_t temp[16] = {0};
  271. StringCchPrintf(status + wcslen(status), 256,
  272. WASABI_API_LNGSTRINGW(IDS_USED_X_X_TRACKS),
  273. usedlen / 60,
  274. usedlen % 60,
  275. itemCache[idx].Size,
  276. WASABI_API_LNGSTRINGW_BUF(itemCache[idx].Size == 1 ? IDS_TRACK : IDS_TRACKS,temp,16));
  277. if (freesecs && pmi->bInserted)
  278. {
  279. if (m_availsecs >= 0) StringCchPrintf(status + wcslen(status), 256, WASABI_API_LNGSTRINGW(IDS_AVAILABLE_X_X),
  280. m_availsecs / 60, m_availsecs % 60);
  281. else StringCchPrintf(status + wcslen(status), 256, WASABI_API_LNGSTRINGW(IDS_X_OVER_CAPACITY_REMOVE_X_TRACKS),
  282. -m_availsecs / 60, -m_availsecs % 60, truncpos);
  283. }
  284. SetDlgItemText(hwndDlg, IDC_CDINFO, status);
  285. m_last_trackpos = -1;
  286. m_is_cdrw = pmi->bRewritable;
  287. ListView_RedrawItems(m_statuslist.getwnd(), 0, itemCache[idx].Size - 1);
  288. }
  289. static void SetStatus(HWND hwndDlg, CHAR cLetter)
  290. {
  291. if (DM_MODE_BURNING == DriveManager_GetDriveMode(cLetter) &&
  292. NULL != (m_burning_other_wnd = cdburn_FindBurningHWND(cLetter)))
  293. {
  294. prevWnd = (HWND)SendMessage(m_burning_other_wnd, WM_BURNUPDATEOWNER, 0, (LPARAM)hwndDlg);
  295. if (prevWnd == hwndDlg) prevWnd = NULL;
  296. DWORD state = (DWORD)(INT_PTR)SendMessage(m_burning_other_wnd, WM_BURNGETSTATUS, BURNSTATUS_STATE, 0);
  297. if (state)
  298. {
  299. SetDlgItemText(hwndDlg, IDC_CDINFO, WASABI_API_LNGSTRINGW(IDS_BURNING));
  300. ShowWindow(GetDlgItem(hwndDlg, IDC_CLEAR), SW_HIDE);
  301. ShowWindow(GetDlgItem(hwndDlg, IDC_ADD), SW_HIDE);
  302. ShowWindow(GetDlgItem(hwndDlg, IDC_BURN), SW_HIDE);
  303. ShowWindow(GetDlgItem(hwndDlg, IDC_BURN_OPTS), SW_SHOWNA);
  304. ShowWindow(GetDlgItem(hwndDlg, IDC_CANCEL_BURN), SW_SHOWNA);
  305. SetDlgItemText(hwndDlg, IDC_CANCEL_BURN, WASABI_API_LNGSTRINGW(IDS_CANCEL_BURN));
  306. m_availsecs = 0;
  307. m_last_trackpos = -1;
  308. m_is_cdrw = 0;
  309. percentCompleted = 0;
  310. UpdateWindow(hwndDlg);
  311. }
  312. SendMessage(hwndDlg, WM_BURNNOTIFY, BURN_STATECHANGED, state);
  313. ShowWindow(m_burning_other_wnd, g_config->ReadInt(L"cdburnstatuswnd", 1) ? SW_SHOWNA : SW_HIDE);
  314. PostMessage(m_burning_other_wnd, WM_BURNCONFIGCHANGED, BURNCFG_HIDEVIEW, !g_config->ReadInt(L"cdburnstatuswnd", 1));
  315. PostMessage(m_burning_other_wnd, WM_BURNCONFIGCHANGED, BURNCFG_AUTOEJECT, g_config->ReadInt(L"cdburnautoeject", 1));
  316. PostMessage(m_burning_other_wnd, WM_BURNCONFIGCHANGED, BURNCFG_ADDTODB, g_config->ReadInt(L"cdburnautoadddb", 0));
  317. PostMessage(m_burning_other_wnd, WM_BURNCONFIGCHANGED, BURNCFG_AUTOCLOSE, g_config->ReadInt(L"cdburnautoclose", 0));
  318. }
  319. else
  320. {
  321. BOOL br;
  322. ShowWindow(GetDlgItem(hwndDlg, IDC_CLEAR), SW_SHOWNA);
  323. ShowWindow(GetDlgItem(hwndDlg, IDC_ADD), SW_SHOWNA);
  324. ShowWindow(GetDlgItem(hwndDlg, IDC_BURN), SW_SHOWNA);
  325. ShowWindow(GetDlgItem(hwndDlg, IDC_BURN_OPTS), SW_HIDE);
  326. ShowWindow(GetDlgItem(hwndDlg, IDC_CANCEL_BURN), SW_HIDE);
  327. SetDlgItemText(hwndDlg, IDC_CDINFO, WASABI_API_LNGSTRINGW(IDS_CALCULATING));
  328. UpdateWindow(hwndDlg);
  329. DM_IMAPI_PARAM *pIMAPI = (DM_IMAPI_PARAM*)calloc(1, sizeof(DM_IMAPI_PARAM));
  330. if (pIMAPI)
  331. {
  332. pIMAPI->header.cLetter = cLetter;
  333. pIMAPI->header.callback = (INT_PTR)hwndDlg;
  334. pIMAPI->header.uMsg = WM_EX_OPCOMPLETED;
  335. pIMAPI->header.fnFree = FreeAsyncParam;
  336. pIMAPI->header.fFlags = DMF_QUERYMEDIATYPE | DMF_QUERYMEDIAINFO;
  337. br = DriveManager_GetIMAPIInfo(pIMAPI);
  338. }
  339. else br = FALSE;
  340. if (!br) SetDlgItemText(hwndDlg, IDC_CDINFO, WASABI_API_LNGSTRINGW(IDS_DISC_READ_ERROR));
  341. }
  342. }
  343. static void deleteSelectedItems(HWND hwndDlg, CHAR cLetter)
  344. {
  345. int idx = LETTERTOINDEX(cLetter);
  346. for (int i = itemCache[idx].Size - 1;i >= 0;i--)
  347. {
  348. if (m_statuslist.GetSelected(i))
  349. {
  350. freeRecord(&itemCache[idx].Items[i]);
  351. int l = itemCache[idx].Size - i - 1;
  352. if (l > 0) memcpy(&itemCache[idx].Items[i], &itemCache[idx].Items[i + 1], sizeof(itemRecordW)*l);
  353. itemCache[idx].Size--;
  354. }
  355. }
  356. SetStatus(hwndDlg, cLetter);
  357. refreshList();
  358. }
  359. static void selectAll()
  360. {
  361. int l = m_statuslist.GetCount();
  362. for (int i = 0;i < l;i++) m_statuslist.SetSelected(i);
  363. }
  364. static void playSelectedItems(HWND hwndDlg, int enqueue)
  365. {
  366. int idx = LETTERTOINDEX(m_cdrom);
  367. if (!enqueue) SendMessage(plugin.hwndWinampParent, WM_WA_IPC, 0, IPC_DELETE);
  368. for (int i = 0;i < itemCache[idx].Size;i++)
  369. {
  370. if (!m_statuslist.GetSelected(i)) continue;
  371. //send the file to winamp
  372. COPYDATASTRUCT cds;
  373. cds.dwData = IPC_PLAYFILEW;
  374. cds.lpData = (void *)itemCache[idx].Items[i].filename;
  375. cds.cbData = (DWORD)(sizeof(wchar_t *) * (wcslen(itemCache[idx].Items[i].filename) + 1)); // include space for null char
  376. SendMessageW(plugin.hwndWinampParent, WM_COPYDATA, (WPARAM)NULL, (LPARAM)&cds);
  377. }
  378. if (!enqueue) SendMessageW(plugin.hwndWinampParent, WM_WA_IPC, 0, IPC_STARTPLAY);
  379. }
  380. BOOL CALLBACK CantBurnProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  381. {
  382. switch (msg)
  383. {
  384. case WM_INITDIALOG:
  385. {
  386. wchar_t *message = (wchar_t *)lParam;
  387. // due to quirks with the more common resource editors, is easier to just store the string
  388. // internally only with \n and post-process to be \r\n (as here) so it will appear correctly
  389. // on new lines as is wanted (silly multiline edit controls)
  390. wchar_t tmp2[1024] = {0}, *t2 = tmp2;
  391. while(message && *message && (t2 - tmp2 < 1024))
  392. {
  393. if(*message == L'\n')
  394. {
  395. *t2 = L'\r';
  396. t2 = CharNextW(t2);
  397. }
  398. *t2 = *message;
  399. message = CharNextW(message);
  400. t2 = CharNextW(t2);
  401. }
  402. SetDlgItemText(hwnd, IDC_MESSAGE2, tmp2);
  403. }
  404. return 0;
  405. case WM_COMMAND:
  406. switch (LOWORD(wParam))
  407. {
  408. case IDOK:
  409. EndDialog(hwnd, 0);
  410. break;
  411. case IDCANCEL:
  412. EndDialog(hwnd, -1);
  413. break;
  414. }
  415. }
  416. return 0;
  417. }
  418. HRESULT ResolveShortCut(HWND hwnd, LPCSTR pszShortcutFile, LPSTR pszPath)
  419. {
  420. HRESULT hres;
  421. IShellLinkA* psl;
  422. WIN32_FIND_DATAA wfd;
  423. *pszPath = 0; // assume failure
  424. hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
  425. IID_IShellLinkA, (void **) & psl);
  426. if (SUCCEEDED(hres))
  427. {
  428. IPersistFile* ppf;
  429. hres = psl->QueryInterface(IID_IPersistFile, (void **) & ppf); // OLE 2! Yay! --YO
  430. if (SUCCEEDED(hres))
  431. {
  432. wchar_t wsz[MAX_PATH] = {0};
  433. MultiByteToWideCharSZ(CP_ACP, 0, pszShortcutFile, -1, wsz, MAX_PATH);
  434. hres = ppf->Load(wsz, STGM_READ);
  435. if (SUCCEEDED(hres))
  436. {
  437. hres = psl->Resolve(hwnd, SLR_ANY_MATCH);
  438. if (SUCCEEDED(hres))
  439. {
  440. char szGotPath[MAX_PATH] = {0};
  441. lstrcpynA(szGotPath, pszShortcutFile, MAX_PATH);
  442. hres = psl->GetPath(szGotPath, MAX_PATH, (WIN32_FIND_DATAA *) & wfd,
  443. SLGP_SHORTPATH);
  444. lstrcpynA(pszPath, szGotPath, MAX_PATH);
  445. }
  446. }
  447. ppf->Release();
  448. }
  449. psl->Release();
  450. }
  451. return SUCCEEDED(hres);
  452. }
  453. HRESULT ResolveShortCut(HWND hwnd, LPCWSTR pszShortcutFile, LPWSTR pszPath)
  454. {
  455. HRESULT hres;
  456. IShellLinkW* psl;
  457. WIN32_FIND_DATAW wfd;
  458. *pszPath = 0; // assume failure
  459. hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
  460. IID_IShellLinkW, (void **) & psl);
  461. if (SUCCEEDED(hres))
  462. {
  463. IPersistFile* ppf;
  464. hres = psl->QueryInterface(IID_IPersistFile, (void **) & ppf); // OLE 2! Yay! --YO
  465. if (SUCCEEDED(hres))
  466. {
  467. /*wchar_t wsz[MAX_PATH] = {0};
  468. MultiByteToWideCharSZ(CP_ACP, 0, pszShortcutFile, -1, wsz, MAX_PATH);*/
  469. hres = ppf->Load(pszShortcutFile/*wsz*/, STGM_READ);
  470. if (SUCCEEDED(hres))
  471. {
  472. hres = psl->Resolve(hwnd, SLR_ANY_MATCH);
  473. if (SUCCEEDED(hres))
  474. {
  475. wchar_t szGotPath[MAX_PATH] = {0};
  476. wcsncpy(szGotPath, pszShortcutFile, MAX_PATH);
  477. hres = psl->GetPath(szGotPath, MAX_PATH, (WIN32_FIND_DATAW *) & wfd,
  478. SLGP_SHORTPATH);
  479. wcsncpy(pszPath, szGotPath, MAX_PATH);
  480. }
  481. }
  482. ppf->Release();
  483. }
  484. psl->Release();
  485. }
  486. return SUCCEEDED(hres);
  487. }
  488. static int checkFile(const char *file)
  489. {
  490. //check if the file is supported by winamp
  491. const char *ext = extension(file);
  492. if (!ext || !ext[0]) return 0;
  493. if (strstr(file, "://") && !strstr(file, "cda://")) return 0;
  494. #if 0 // benski> this would be neat to have, but will fail with unicode filenames (which in_mp3 can open anyway)... TODO: make it workable later
  495. HANDLE hFile = CreateFile(file, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  496. if (INVALID_HANDLE_VALUE == hFile && GetLastError() != ERROR_FILE_NOT_FOUND)
  497. {
  498. wchar_t message[1024] = {0};
  499. StringCchPrintfW(message, 1024, WASABI_API_LNGSTRINGW(IDS_FILE_X_CANNOT_BE_BURNED_REASON_NOT_FOUND), AutoWide(file), AutoWide(ext));
  500. return WASABI_API_DIALOGBOXPARAM(IDD_NOBURN, g_hwnd, CantBurnProc, (LPARAM)message);
  501. }
  502. CloseHandle(hFile);
  503. #endif
  504. char *m_extlist = (char*)SendMessage(plugin.hwndWinampParent, WM_WA_IPC, 0, IPC_GET_EXTLIST);
  505. {
  506. int found = 0;
  507. char *a = m_extlist;
  508. while (a && *a)
  509. {
  510. if (!lstrcmpiA(a, ext))
  511. {
  512. found = 1;
  513. break;
  514. }
  515. a += lstrlenA(a) + 1;
  516. }
  517. GlobalFree((HGLOBAL)m_extlist);
  518. if (!found)
  519. {
  520. wchar_t message[1024] = {0};
  521. StringCchPrintfW(message, 1024, WASABI_API_LNGSTRINGW(IDS_FILE_X_CANNOT_BE_BURNED_REASON_FILETYPE_NOT_REGISTERED), AutoWide(file), AutoWide(ext));
  522. return (int)(INT_PTR)WASABI_API_DIALOGBOXPARAM(IDD_NOBURN, plugin.hwndLibraryParent, CantBurnProc, (LPARAM)message);
  523. }
  524. }
  525. //check for type
  526. char tmp[64] = {0, };
  527. getFileInfo(file, "type", tmp, sizeof(tmp) - 1);
  528. if (tmp[0] && tmp[0] != '0')
  529. {
  530. wchar_t message[1024], temp[128] = {0};
  531. StringCchPrintfW(message, 1024, WASABI_API_LNGSTRINGW(IDS_FILE_X_CANNOT_BE_BURNED_REASON_X),AutoWide(file),
  532. WASABI_API_LNGSTRINGW_BUF((tmp[0] == '1' ? IDS_VIDEO_FILES_CANNOT_BE_BURNED : IDS_NOT_AN_AUDIO_FILE),temp,128));
  533. return (int)(INT_PTR)WASABI_API_DIALOGBOXPARAM(IDD_NOBURN, plugin.hwndLibraryParent, CantBurnProc, (LPARAM)message);
  534. }
  535. // note: this check is NOT meant as any sort of protection.. It simply saves the user the hassle of an error later
  536. if (getFileInfo(file, "burnable", tmp, 64) // most plugins don't support this extended file info, so failure is OK
  537. && tmp[0] == '0') // if it does support it, then we can check whether or not it's burnable
  538. {
  539. wchar_t message[1024] = {0};
  540. StringCchPrintfW(message, 1024, WASABI_API_LNGSTRINGW(IDS_FILE_CANNOT_BE_BURNED), AutoWide(file));
  541. if (getFileInfo(file, "noburnreason", tmp, 64))
  542. {
  543. StringCchPrintfW(message, 1024,
  544. WASABI_API_LNGSTRINGW(IDS_FILE_X_CANNOT_BE_BURNED_REASON_X),
  545. AutoWide(file), AutoWide(tmp));
  546. }
  547. return (int)(INT_PTR)WASABI_API_DIALOGBOXPARAM(IDD_NOBURN, plugin.hwndLibraryParent, CantBurnProc, (LPARAM)message);
  548. }
  549. return 1;
  550. }
  551. static int checkFile(const wchar_t *file)
  552. {
  553. //check if the file is supported by winamp
  554. const wchar_t *ext = PathFindExtension(file);
  555. if (!ext || !ext[0]) return 0;
  556. ext++;
  557. if (wcsstr(file, L"://") && !wcsstr(file, L"cda://")) return 0;
  558. #if 0 // benski> this would be neat to have, but will fail with unicode filenames (which in_mp3 can open anyway)... TODO: make it workable later
  559. HANDLE hFile = CreateFile(file, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  560. if (INVALID_HANDLE_VALUE == hFile && GetLastError() == ERROR_FILE_NOT_FOUND)
  561. {
  562. wchar_t message[1024] = {0};
  563. StringCchPrintfW(message, 1024, WASABI_API_LNGSTRINGW(IDS_FILE_X_CANNOT_BE_BURNED_REASON_NOT_FOUND), file, ext);
  564. return WASABI_API_DIALOGBOXPARAM(IDD_NOBURN, g_hwnd, CantBurnProc, (LPARAM)message);
  565. }
  566. CloseHandle(hFile);
  567. #endif
  568. wchar_t *m_extlist = (wchar_t*)SendMessage(plugin.hwndWinampParent, WM_WA_IPC, 0, IPC_GET_EXTLISTW);
  569. {
  570. int found = 0;
  571. wchar_t *a = m_extlist;
  572. while (a && *a)
  573. {
  574. if (!lstrcmpiW(a, ext))
  575. {
  576. found = 1;
  577. break;
  578. }
  579. a += lstrlenW(a) + 1;
  580. }
  581. GlobalFree((HGLOBAL)m_extlist);
  582. if (!found)
  583. {
  584. wchar_t message[1024] = {0};
  585. StringCchPrintfW(message, 1024, WASABI_API_LNGSTRINGW(IDS_FILE_X_CANNOT_BE_BURNED_REASON_FILETYPE_NOT_REGISTERED), file, ext);
  586. return (int)(INT_PTR)WASABI_API_DIALOGBOXPARAM(IDD_NOBURN, plugin.hwndLibraryParent, CantBurnProc, (LPARAM)message);
  587. }
  588. }
  589. //check for type
  590. wchar_t tmp[64] = {0, };
  591. getFileInfoW(file, L"type", tmp, 64);
  592. if (tmp[0] && tmp[0] != '0')
  593. {
  594. wchar_t message[1024] = {0}, temp[128] = {0};
  595. StringCchPrintfW(message, 1024, WASABI_API_LNGSTRINGW(IDS_FILE_X_CANNOT_BE_BURNED_REASON_X), file,
  596. WASABI_API_LNGSTRINGW_BUF((tmp[0] == '1' ? IDS_VIDEO_FILES_CANNOT_BE_BURNED : IDS_NOT_AN_AUDIO_FILE),temp,128));
  597. return (int)(INT_PTR)WASABI_API_DIALOGBOXPARAM(IDD_NOBURN, plugin.hwndLibraryParent, CantBurnProc, (LPARAM)message);
  598. }
  599. // note: this check is NOT meant as any sort of protection.. It simply saves the user the hassle of an error later
  600. if (getFileInfoW(file, L"burnable", tmp, 64) // most plugins don't support this extended file info, so failure is OK
  601. && tmp[0] == '0') // if it does support it, then we can check whether or not it's burnable
  602. {
  603. wchar_t message[1024] = {0};
  604. StringCchPrintfW(message, 1024, WASABI_API_LNGSTRINGW(IDS_FILE_CANNOT_BE_BURNED), file);
  605. if (getFileInfoW(file, L"noburnreason", tmp, 64))
  606. {
  607. StringCchPrintfW(message, 1024,
  608. WASABI_API_LNGSTRINGW(IDS_FILE_X_CANNOT_BE_BURNED_REASON_X),
  609. file, tmp);
  610. }
  611. return (int)(INT_PTR)WASABI_API_DIALOGBOXPARAM(IDD_NOBURN, plugin.hwndLibraryParent, CantBurnProc, (LPARAM)message);
  612. }
  613. return 1;
  614. }
  615. void cdburn_clearBurner(char driveletter)
  616. {
  617. emptyRecordList(&itemCache[LETTERTOINDEX(driveletter)]);
  618. }
  619. void cdburn_addfile(char* file, std::vector<GayString*> *files, api_playlistmanager* plManager, ifc_playlistloadercallback *plCB);
  620. void cdburn_addfile(wchar_t* file, std::vector<GayStringW*> *files, api_playlistmanager* plManager, ifc_playlistloadercallback *plCB);
  621. void cdburn_addfolder(const char* folder, std::vector<GayString*> *files, api_playlistmanager* plManager, ifc_playlistloadercallback *plCB);
  622. void cdburn_addfolder(const wchar_t* folder, std::vector<GayStringW*> *files, api_playlistmanager* plManager, ifc_playlistloadercallback *plCB);
  623. void cdburn_appendFile(char *file, char cLetter)
  624. {
  625. std::vector<GayString*> files;
  626. waServiceFactory *plmFactory = plugin.service->service_getServiceByGuid(api_playlistmanagerGUID);
  627. api_playlistmanager *plManager = (plmFactory) ? (api_playlistmanager*)plmFactory->getInterface() : NULL;
  628. int idx = LETTERTOINDEX(cLetter);
  629. int validFile = 1;
  630. if (itemCache[idx].Size > 255) return;
  631. itemRecordListW newItems = {0, 0, 0};
  632. PLCallBack plCB;
  633. plCB.fileList = &files;
  634. cdburn_addfile(file, &files, (api_playlistmanager*)plManager, (ifc_playlistloadercallback*)&plCB);
  635. size_t x;
  636. for (x = 0; x < files.size(); x ++) // temp record . replace it !!!
  637. {
  638. char *fn = files.at(x)->Get();
  639. validFile = checkFile(fn);
  640. // can't use switch here cause break won't work
  641. if (validFile == -1) // bad file and user cancelled
  642. break;
  643. if (validFile) // bad file, user skipped
  644. {
  645. allocRecordList(&newItems, newItems.Size + 1);
  646. if (!newItems.Alloc) break;
  647. char title[2048] = {0};
  648. basicFileInfoStruct bfis = {fn, 0, 0, title, sizeof(title) - 1,};
  649. SendMessage(plugin.hwndWinampParent, WM_WA_IPC, (WPARAM)&bfis, IPC_GET_BASIC_FILE_INFO);
  650. if (bfis.length > 0)
  651. {
  652. memset((void *)&(newItems.Items[newItems.Size]), 0, sizeof(itemRecordW));
  653. newItems.Items[newItems.Size].filename = AutoWideDup(fn);
  654. newItems.Items[newItems.Size].title = AutoWideDup(title);
  655. newItems.Items[newItems.Size].length = bfis.length;
  656. newItems.Size++;
  657. }
  658. }
  659. delete(files.at(x)->Get());
  660. }
  661. if (validFile != -1)
  662. copyRecordList(&itemCache[idx], &newItems);
  663. refreshList();
  664. if (m_hwndstatus) SetStatus(m_hwndstatus, cLetter);
  665. if (plManager) plmFactory->releaseInterface(plManager);
  666. }
  667. void cdburn_appendFile(wchar_t *file, char cLetter)
  668. {
  669. std::vector<GayStringW*> files;
  670. waServiceFactory *plmFactory = plugin.service->service_getServiceByGuid(api_playlistmanagerGUID);
  671. api_playlistmanager *plManager = (plmFactory) ? (api_playlistmanager*)plmFactory->getInterface() : NULL;
  672. int idx = LETTERTOINDEX(cLetter);
  673. int validFile = 1;
  674. if (itemCache[idx].Size > 255) return;
  675. itemRecordListW newItems = {0, 0, 0};
  676. PLCallBackW plCB;
  677. plCB.fileList = &files;
  678. cdburn_addfile(file, &files, (api_playlistmanager*)plManager, (ifc_playlistloadercallback*)&plCB);
  679. size_t x;
  680. for (x = 0; x < files.size(); x ++) // temp record . replace it !!!
  681. {
  682. const wchar_t *fn = files.at(x)->Get();
  683. validFile = checkFile(fn);
  684. // can't use switch here cause break won't work
  685. if (validFile == -1) // bad file and user cancelled
  686. break;
  687. if (validFile) // bad file, user skipped
  688. {
  689. allocRecordList(&newItems, newItems.Size + 1);
  690. if (!newItems.Alloc) break;
  691. wchar_t title[2048] = {0};
  692. basicFileInfoStructW bfis = {fn, 0, 0, title, ARRAYSIZE(title) - 1,};
  693. SendMessage(plugin.hwndWinampParent, WM_WA_IPC, (WPARAM)&bfis, IPC_GET_BASIC_FILE_INFOW);
  694. if (bfis.length > 0)
  695. {
  696. memset((void *)&(newItems.Items[newItems.Size]), 0, sizeof(itemRecordW));
  697. newItems.Items[newItems.Size].filename = _wcsdup(fn);
  698. newItems.Items[newItems.Size].title = _wcsdup(title);
  699. newItems.Items[newItems.Size].length = bfis.length;
  700. newItems.Size++;
  701. }
  702. }
  703. delete(files.at(x)->Get());
  704. }
  705. if (validFile != -1)
  706. copyRecordList(&itemCache[idx], &newItems);
  707. refreshList();
  708. if (m_hwndstatus) SetStatus(m_hwndstatus, cLetter);
  709. if (plManager) plmFactory->releaseInterface(plManager);
  710. }
  711. void cdburn_addfile(char* file, std::vector<GayString*> *files, api_playlistmanager* plManager, ifc_playlistloadercallback *plCB)
  712. {
  713. if (!_stricmp(extension(file), "lnk"))
  714. {
  715. char temp2[MAX_PATH] = {0};
  716. if (ResolveShortCut(plugin.hwndLibraryParent, file, temp2)) lstrcpynA(file, temp2, MAX_PATH);
  717. else return;
  718. }
  719. if (!_strnicmp(file, "cda://", 6))
  720. {
  721. if (strlen(file) == 7)
  722. {
  723. int n = 0;
  724. char buf2[32] = {0};
  725. getFileInfo(file, "ntracks", buf2, sizeof(buf2));
  726. n = atoi(buf2);
  727. if (n > 0 && n < 256)
  728. {
  729. for (int x = 0; x < n; x ++)
  730. {
  731. char s[64] = {0};
  732. StringCchPrintfA(s, 64, "%s,%d.cda", file, x + 1);
  733. files->push_back(new GayString(s));
  734. }
  735. }
  736. }
  737. else files->push_back(new GayString(file));
  738. }
  739. else if (strstr(file, "://"))
  740. {
  741. if (plManager && PLAYLISTMANAGER_SUCCESS != plManager->Load(AutoWide(file), plCB))
  742. {
  743. files->push_back(new GayString(file));
  744. }
  745. }
  746. else if (!lstrcmpA(file + 1, ":\\"))
  747. {
  748. cdburn_addfolder(file, files, plManager, plCB);
  749. }
  750. else
  751. {
  752. WIN32_FIND_DATAA d = {0};
  753. HANDLE h = FindFirstFileA(file, &d);
  754. if (h != INVALID_HANDLE_VALUE)
  755. {
  756. FindClose(h);
  757. if (d.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  758. {
  759. cdburn_addfolder(file, files, plManager, plCB);
  760. }
  761. if (plManager && PLAYLISTMANAGER_SUCCESS != plManager->Load(AutoWide(file), plCB))
  762. {
  763. files->push_back(new GayString(file));
  764. }
  765. }
  766. else files->push_back(new GayString(file));
  767. }
  768. }
  769. void cdburn_addfile(wchar_t* file, std::vector<GayStringW*> *files, api_playlistmanager* plManager, ifc_playlistloadercallback *plCB)
  770. {
  771. if (!_wcsicmp(extensionW(file), L"lnk"))
  772. {
  773. wchar_t temp2[MAX_PATH] = {0};
  774. if (ResolveShortCut(plugin.hwndLibraryParent, file, temp2)) lstrcpyn(file, temp2, MAX_PATH);
  775. else return;
  776. }
  777. if (!_wcsnicmp(file, L"cda://", 6))
  778. {
  779. if (wcslen(file) == 7)
  780. {
  781. int n = 0;
  782. wchar_t buf2[32] = {0};
  783. getFileInfoW(file, L"ntracks", buf2, sizeof(buf2));
  784. n = _wtoi(buf2);
  785. if (n > 0 && n < 256)
  786. {
  787. for (int x = 0; x < n; x ++)
  788. {
  789. wchar_t s[64] = {0};
  790. StringCchPrintfW(s, 64, L"%s,%d.cda", file, x + 1);
  791. files->push_back(new GayStringW(s));
  792. }
  793. }
  794. }
  795. else files->push_back(new GayStringW(file));
  796. }
  797. else if (wcsstr(file, L"://"))
  798. {
  799. if (plManager && PLAYLISTMANAGER_SUCCESS != plManager->Load(file, plCB))
  800. {
  801. files->push_back(new GayStringW(file));
  802. }
  803. }
  804. else if (!lstrcmpW(file + 1, L":\\"))
  805. {
  806. cdburn_addfolder(file, files, plManager, plCB);
  807. }
  808. else
  809. {
  810. WIN32_FIND_DATAW d = {0};
  811. HANDLE h = FindFirstFileW(file, &d);
  812. if (h != INVALID_HANDLE_VALUE)
  813. {
  814. FindClose(h);
  815. if (d.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  816. {
  817. cdburn_addfolder(file, files, plManager, plCB);
  818. }
  819. if (plManager && PLAYLISTMANAGER_SUCCESS != plManager->Load(file, plCB))
  820. {
  821. files->push_back(new GayStringW(file));
  822. }
  823. }
  824. else files->push_back(new GayStringW(file));
  825. }
  826. }
  827. void cdburn_addfolder(const char* folder, std::vector<GayString*> *files, api_playlistmanager* plManager, ifc_playlistloadercallback *plCB)
  828. {
  829. WIN32_FIND_DATAA d = {0};
  830. char path[MAX_PATH] = {0};
  831. PathCombineA(path, folder, "*");
  832. HANDLE h = FindFirstFileA(path, &d);
  833. if (h == INVALID_HANDLE_VALUE) return;
  834. do
  835. {
  836. if (d.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  837. {
  838. if (0 == lstrcmpA(d.cFileName, ".") || 0 == lstrcmpA(d.cFileName, "..")) continue;
  839. GayString pathNew(folder);
  840. pathNew.Append("\\");
  841. pathNew.Append(d.cFileName);
  842. cdburn_addfolder(pathNew.Get(), files, plManager, plCB);
  843. }
  844. else
  845. {
  846. GayString file(folder);
  847. file.Append("\\");
  848. file.Append(d.cFileName);
  849. cdburn_addfile(file.Get(), files, plManager, plCB);
  850. }
  851. }
  852. while (FindNextFileA(h, &d));
  853. FindClose(h);
  854. }
  855. void cdburn_addfolder(const wchar_t* folder, std::vector<GayStringW*> *files, api_playlistmanager* plManager, ifc_playlistloadercallback *plCB)
  856. {
  857. WIN32_FIND_DATAW d = {0};
  858. wchar_t path[MAX_PATH] = {0};
  859. PathCombineW(path, folder, L"*");
  860. HANDLE h = FindFirstFileW(path, &d);
  861. if (h == INVALID_HANDLE_VALUE) return;
  862. do
  863. {
  864. if (d.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  865. {
  866. if (0 == lstrcmpW(d.cFileName, L".") || 0 == lstrcmpW(d.cFileName, L"..")) continue;
  867. GayStringW pathNew(folder);
  868. pathNew.Append(L"\\");
  869. pathNew.Append(d.cFileName);
  870. cdburn_addfolder(pathNew.Get(), files, plManager, plCB);
  871. }
  872. else
  873. {
  874. GayStringW file(folder);
  875. file.Append(L"\\");
  876. file.Append(d.cFileName);
  877. cdburn_addfile((wchar_t*)file.Get(), files, plManager, plCB);
  878. }
  879. }
  880. while (FindNextFileW(h, &d));
  881. FindClose(h);
  882. }
  883. void cdburn_appendItemRecord(itemRecordList *obj, char cLetter)
  884. {
  885. int idx = LETTERTOINDEX(cLetter);
  886. int validFile = 1;
  887. itemRecordListW newItems = {0, 0, 0};
  888. BurnAddStatus_Create(obj->Size);
  889. for (int i = 0;i < obj->Size;i++)
  890. {
  891. validFile = checkFile(obj->Items[i].filename);
  892. if (validFile == -1)
  893. break;
  894. if (validFile)
  895. {
  896. if (newItems.Size > 255) break;
  897. allocRecordList(&newItems, newItems.Size + 1);
  898. if (!newItems.Alloc) return ;
  899. memset((void *)&(newItems.Items[newItems.Size]), 0, sizeof(itemRecordW));
  900. newItems.Items[newItems.Size].filename = AutoWideDup(obj->Items[i].filename);
  901. GayString title;
  902. if (obj->Items[i].artist) title.Append(obj->Items[i].artist);
  903. if (title.Get() && title.Get()[0] && obj->Items[i].title && obj->Items[i].title[0])
  904. title.Append(" - ");
  905. if (obj->Items[i].title) title.Append(obj->Items[i].title);
  906. newItems.Items[newItems.Size].title = AutoWideDup(title.Get());
  907. newItems.Items[newItems.Size].length = obj->Items[i].length;
  908. newItems.Size++;
  909. BurnAddStatus_Step(&newItems);
  910. }
  911. }
  912. BurnAddStatus_Done();
  913. if (validFile != -1)
  914. copyRecordList(&itemCache[idx], &newItems);
  915. refreshList();
  916. if (m_hwndstatus) SetStatus(m_hwndstatus, cLetter);
  917. }
  918. void cdburn_appendItemRecord(itemRecordListW *obj, char cLetter)
  919. {
  920. int idx = LETTERTOINDEX(cLetter);
  921. int validFile = 1;
  922. itemRecordListW newItems = {0, 0, 0};
  923. BurnAddStatus_Create(obj->Size);
  924. for (int i = 0;i < obj->Size;i++)
  925. {
  926. validFile = checkFile(obj->Items[i].filename);
  927. if (validFile == -1)
  928. break;
  929. if (validFile)
  930. {
  931. if (newItems.Size > 255) break;
  932. allocRecordList(&newItems, newItems.Size + 1);
  933. if (!newItems.Alloc) return ;
  934. memset((void *)&(newItems.Items[newItems.Size]), 0, sizeof(itemRecordW));
  935. newItems.Items[newItems.Size].filename = _wcsdup(obj->Items[i].filename);
  936. GayStringW title;
  937. if (obj->Items[i].artist) title.Append(obj->Items[i].artist);
  938. if (title.Get() && title.Get()[0] && obj->Items[i].title && obj->Items[i].title[0])
  939. title.Append(L" - ");
  940. if (obj->Items[i].title) title.Append(obj->Items[i].title);
  941. newItems.Items[newItems.Size].title = _wcsdup(title.Get());
  942. newItems.Items[newItems.Size].length = obj->Items[i].length;
  943. newItems.Size++;
  944. BurnAddStatus_Step(&newItems);
  945. }
  946. }
  947. BurnAddStatus_Done();
  948. if (validFile != -1)
  949. copyRecordList(&itemCache[idx], &newItems);
  950. refreshList();
  951. if (m_hwndstatus) SetStatus(m_hwndstatus, cLetter);
  952. }
  953. static void Shell_Free(void *p)
  954. {
  955. IMalloc *m;
  956. SHGetMalloc(&m);
  957. m->Free(p);
  958. }
  959. HWND cdburn_FindBurningHWND(char cLetter)
  960. {
  961. HWND h = 0;
  962. while (NULL != (h = FindWindowExW(NULL, h, L"#32770", NULL)))
  963. {
  964. if (!GetPropW(h, L"WABURNER")) continue;
  965. if (((char)(INT_PTR)GetPropW(h, L"DRIVE")) == cLetter) return h;
  966. }
  967. return NULL;
  968. }
  969. CHAR cdburn_IsMeBurning(void)
  970. {
  971. if (pidBurner)
  972. {
  973. HWND h = NULL;
  974. DWORD pid;
  975. while (NULL != (h = FindWindowExW(NULL, h, L"#32770", NULL)))
  976. {
  977. if (GetPropW(h, L"WABURNER") && GetWindowThreadProcessId(h, &pid) && pid == pidBurner)
  978. return (CHAR)(INT_PTR)GetPropW(h, L"DRIVE");
  979. }
  980. }
  981. return 0;
  982. }
  983. static void NotifyInfoWindow(HWND hwnd, LPCWSTR pszFileName, BOOL bForceRefresh)
  984. {
  985. HWND hwndParent;
  986. hwndParent = GetParent(hwnd);
  987. if (hwndParent) SendMessageW(hwndParent, WM_SHOWFILEINFO,
  988. (WPARAM)((bForceRefresh) ? WISF_FORCE : WISF_NORMAL),
  989. (LPARAM)pszFileName);
  990. }
  991. static void moveSelItemsUp()
  992. {
  993. if (DM_MODE_BURNING == DriveManager_GetDriveMode(m_cdrom)) return;
  994. int idx = LETTERTOINDEX(m_cdrom);
  995. for (int i = 0;i < itemCache[idx].Size;i++)
  996. {
  997. if (m_statuslist.GetSelected(i))
  998. {
  999. //swap the 2 items
  1000. if (i > 0)
  1001. {
  1002. itemRecordW tmp = itemCache[idx].Items[i];
  1003. itemCache[idx].Items[i] = itemCache[idx].Items[i - 1];
  1004. itemCache[idx].Items[i - 1] = tmp;
  1005. ListView_SetItemState(m_statuslist.getwnd(), i - 1, LVIS_SELECTED, LVIS_SELECTED);
  1006. ListView_SetItemState(m_statuslist.getwnd(), i, 0, LVIS_SELECTED);
  1007. ListView_RedrawItems(m_statuslist.getwnd(), i - 1, i);
  1008. if (ListView_GetItemState(m_statuslist.getwnd(), i, LVIS_FOCUSED))
  1009. {
  1010. ListView_SetItemState(m_statuslist.getwnd(), i - 1, LVIS_FOCUSED, LVIS_FOCUSED);
  1011. }
  1012. }
  1013. }
  1014. }
  1015. }
  1016. static void moveSelItemsDown()
  1017. {
  1018. if (DM_MODE_BURNING == DriveManager_GetDriveMode(m_cdrom)) return ;
  1019. int idx = LETTERTOINDEX(m_cdrom);
  1020. for (int i = itemCache[idx].Size - 1;i >= 0;i--)
  1021. {
  1022. if (m_statuslist.GetSelected(i))
  1023. {
  1024. //swap the 2 items
  1025. if (i < (itemCache[idx].Size - 1))
  1026. {
  1027. itemRecordW tmp = itemCache[idx].Items[i];
  1028. itemCache[idx].Items[i] = itemCache[idx].Items[i + 1];
  1029. itemCache[idx].Items[i + 1] = tmp;
  1030. ListView_SetItemState(m_statuslist.getwnd(), i + 1, LVIS_SELECTED, LVIS_SELECTED);
  1031. ListView_SetItemState(m_statuslist.getwnd(), i, 0, LVIS_SELECTED);
  1032. ListView_RedrawItems(m_statuslist.getwnd(), i, i + 1);
  1033. if (ListView_GetItemState(m_statuslist.getwnd(), i, LVIS_FOCUSED))
  1034. {
  1035. ListView_SetItemState(m_statuslist.getwnd(), i + 1, LVIS_FOCUSED, LVIS_FOCUSED);
  1036. }
  1037. }
  1038. }
  1039. }
  1040. }
  1041. int g_burn_hack_startburn;
  1042. void OnBurnDlgInit(HWND hwndDlg, LPARAM lParam)
  1043. {
  1044. m_hwndstatus = hwndDlg;
  1045. m_is_cdrw = 0;
  1046. m_dragging = 0;
  1047. m_cdrom = (char)lParam;
  1048. SendMessageW(GetParent(hwndDlg), WM_COMMAND, MAKEWPARAM(IDC_BTN_SHOWINFO, BN_EX_GETTEXT), (LPARAM)GetDlgItem(hwndDlg, IDC_BTN_SHOWINFO));
  1049. m_statuslist.setwnd(GetDlgItem(hwndDlg, IDC_LIST2));
  1050. m_statuslist.AddCol(WASABI_API_LNGSTRINGW(IDS_TRACK_NUMBER), g_view_metaconf->ReadInt(L"col_track", 60));
  1051. m_statuslist.AddCol(WASABI_API_LNGSTRINGW(IDS_TITLE), g_view_metaconf->ReadInt(L"col_title", 200));
  1052. m_statuslist.AddCol(WASABI_API_LNGSTRINGW(IDS_LENGTH), g_view_metaconf->ReadInt(L"col_len", 80));
  1053. m_statuslist.AddCol(WASABI_API_LNGSTRINGW(IDS_STATUS), g_view_metaconf->ReadInt(L"col_status", 200));
  1054. childSizer.Init(hwndDlg, burnwnd_rlist, sizeof(burnwnd_rlist) / sizeof(burnwnd_rlist[0]));
  1055. if(m_statuslist.getwnd())
  1056. {
  1057. MLSKINWINDOW sw;
  1058. sw.hwndToSkin = m_statuslist.getwnd();
  1059. sw.skinType = SKINNEDWND_TYPE_LISTVIEW;
  1060. sw.style = SWLVS_FULLROWSELECT | SWLVS_DOUBLEBUFFER | SWLVS_ALTERNATEITEMS | SWS_USESKINFONT | SWS_USESKINCOLORS | SWS_USESKINCURSORS;
  1061. MLSkinWindow(plugin.hwndLibraryParent, &sw);
  1062. }
  1063. refreshList();
  1064. // this will make sure that we've got the cddb logo shown even when using a localised version
  1065. HANDLE hPrev = (HANDLE) SendDlgItemMessage(hwndDlg,IDC_LOGO,STM_SETIMAGE,IMAGE_BITMAP,
  1066. (LPARAM)LoadImage(plugin.hDllInstance,MAKEINTRESOURCE(IDB_LISTITEM_CDDRIVE),
  1067. IMAGE_BITMAP,0,0, 0));
  1068. if (hPrev) DeleteObject(hPrev);
  1069. NotifyInfoWindow(hwndDlg, NULL, TRUE); // ignore cache
  1070. SetStatus(hwndDlg, m_cdrom);
  1071. if (g_burn_hack_startburn)
  1072. {
  1073. g_burn_hack_startburn = 0;
  1074. PostMessage(hwndDlg, WM_COMMAND, IDC_BURN, 0);
  1075. }
  1076. }
  1077. void OnBurnNotify(HWND hwndDlg, DWORD notification, DWORD param)
  1078. {
  1079. switch (notification)
  1080. {
  1081. case BURN_READY:
  1082. SetStatus(hwndDlg, m_cdrom);
  1083. break;
  1084. case BURN_STATECHANGED:
  1085. {
  1086. wchar_t title[512] = {0};
  1087. const wchar_t *buf = NULL;
  1088. switch (param)
  1089. {
  1090. case BURNERPLAYLIST_BURNCANCELING:
  1091. SetDlgItemText(hwndDlg, IDC_CANCEL_BURN, WASABI_API_LNGSTRINGW(IDS_CANCELLING));
  1092. buf = WASABI_API_LNGSTRINGW_BUF(IDS_BURNING_AUDIO_CANCELLING,title,512);
  1093. break;
  1094. case BURNERPLAYLIST_BURNFINISHING:
  1095. buf = WASABI_API_LNGSTRINGW_BUF(IDS_BURNING_AUDIO_FINISHING,title,512);
  1096. break;
  1097. case BURNERPLAYLIST_DECODEFINISHED:
  1098. buf = WASABI_API_LNGSTRINGW_BUF(IDS_BURNING_AUDIO_DATA_PREP_FINISHED,title,512);
  1099. break;
  1100. case BURNERPLAYLIST_LICENSINGSTARTING:
  1101. buf = WASABI_API_LNGSTRINGW_BUF(IDS_BURNING_AUDIO_VERIFYING_FILES,title,512);
  1102. break;
  1103. case BURNERPLAYLIST_LICENSINGFINISHED:
  1104. buf = WASABI_API_LNGSTRINGW_BUF(IDS_BURNING_AUDIO_VERIFICATION_COMPLETED,title,512);
  1105. break;
  1106. case BURNERPLAYLIST_BURNPROGRESS:
  1107. wchar_t buf2[256] = {0};
  1108. switch (SendMessage(m_burning_other_wnd, WM_BURNGETSTATUS, BURNSTATUS_ERROR, 0))
  1109. {
  1110. case BURNERPLAYLIST_WRITELEADIN:
  1111. buf = WASABI_API_LNGSTRINGW_BUF(IDS_OPENING_DISC_WRITING_LEAD_IN,buf2,256);
  1112. break;
  1113. case BURNERPLAYLIST_WRITELEADOUT:
  1114. buf = WASABI_API_LNGSTRINGW_BUF(IDS_CLOSING_DISC_WRITING_LEAD_OUT,buf2,256);
  1115. break;
  1116. default: break;
  1117. }
  1118. if (buf)
  1119. {
  1120. int percent = (int)(INT_PTR)SendMessage(m_burning_other_wnd, WM_BURNGETSTATUS, BURNSTATUS_PROGRESS, 0);
  1121. percentCompleted = max(percent, percentCompleted);
  1122. StringCchPrintf(title, 512, WASABI_API_LNGSTRINGW(IDS_BURNING_AUDIO_CURRENT_OPERATION), percentCompleted, buf);
  1123. }
  1124. break;
  1125. }
  1126. if (buf) SetDlgItemText(hwndDlg, IDC_CDINFO, title);
  1127. }
  1128. break;
  1129. case BURN_ITEMSTATECHANGED:
  1130. ListView_RedrawItems(m_statuslist.getwnd(), param, param);
  1131. break;
  1132. case BURN_ITEMDECODEPROGRESS:
  1133. ListView_RedrawItems(m_statuslist.getwnd(), param, param);
  1134. {
  1135. wchar_t title[512] = {0};
  1136. int percent = (int)(INT_PTR)SendMessage(m_burning_other_wnd, WM_BURNGETSTATUS, BURNSTATUS_PROGRESS, 0);
  1137. percentCompleted = max(percent, percentCompleted);
  1138. StringCchPrintf(title, 512, WASABI_API_LNGSTRINGW(IDS_BURNING_AUDIO_CD_PREP_DATA), percentCompleted);
  1139. SetDlgItemText(hwndDlg, IDC_CDINFO, title);
  1140. }
  1141. break;
  1142. case BURN_ITEMBURNPROGRESS:
  1143. ListView_RedrawItems(m_statuslist.getwnd(), param, param);
  1144. {
  1145. wchar_t title[512] = {0};
  1146. int percent = (int)(INT_PTR)SendMessage(m_burning_other_wnd, WM_BURNGETSTATUS, BURNSTATUS_PROGRESS, 0);
  1147. percentCompleted = max(percent, percentCompleted);
  1148. StringCchPrintf(title, 512, WASABI_API_LNGSTRINGW(IDS_BURNING_AUDIO_BURNING_DATA), percentCompleted);
  1149. SetDlgItemText(hwndDlg, IDC_CDINFO, title);
  1150. }
  1151. break;
  1152. case BURN_WORKING:
  1153. ListView_RedrawItems(m_statuslist.getwnd(), 0, ListView_GetItemCount(m_statuslist.getwnd()));
  1154. break;
  1155. case BURN_FINISHED:
  1156. {
  1157. wchar_t buf1[128] = {0}, closeStr[16] = {0};
  1158. GetDlgItemText(hwndDlg, IDC_CANCEL_BURN, buf1, ARRAYSIZE(buf1));
  1159. if (lstrcmpi(buf1, WASABI_API_LNGSTRINGW_BUF(IDS_CLOSE,closeStr,16)))
  1160. SetDlgItemText(hwndDlg, IDC_CANCEL_BURN, closeStr);
  1161. wchar_t buf[128] = {0};
  1162. switch (param)
  1163. {
  1164. case BURNERPLAYLIST_SUCCESS:
  1165. WASABI_API_LNGSTRINGW_BUF(IDS_AUDIO_CD_BURNED_SUCCESSFULLY,buf,128);
  1166. break;
  1167. case BURNERPLAYLIST_ABORTED:
  1168. WASABI_API_LNGSTRINGW_BUF(IDS_BURN_ABORTED_BY_USER,buf,128);
  1169. break;
  1170. default:
  1171. WASABI_API_LNGSTRINGW_BUF(IDS_BURNING_FAILED,buf,128);
  1172. break;
  1173. }
  1174. StringCchPrintf(buf1, 128, WASABI_API_LNGSTRINGW(IDS_BURNING_COMPLETED_STATUS_X), buf);
  1175. SetDlgItemText(hwndDlg, IDC_CDINFO, buf1);
  1176. EnableWindow(GetDlgItem(hwndDlg, IDC_BURN), TRUE);
  1177. EnableWindow(GetDlgItem(hwndDlg, IDC_CANCEL_BURN), TRUE);
  1178. }
  1179. break;
  1180. case BURN_DESTROYED:
  1181. EnableWindow(GetDlgItem(hwndDlg, IDC_BURN), TRUE);
  1182. EnableWindow(GetDlgItem(hwndDlg, IDC_CANCEL_BURN), TRUE);
  1183. m_burning_other_wnd = NULL;
  1184. SetStatus(hwndDlg, m_cdrom);
  1185. break;
  1186. case BURN_CONFIGCHANGED:
  1187. switch (LOWORD(param))
  1188. {
  1189. case BURNCFG_AUTOCLOSE:
  1190. g_config->WriteInt(L"cdburnautoclose", HIWORD(param));
  1191. break;
  1192. case BURNCFG_AUTOEJECT:
  1193. g_config->WriteInt(L"cdburnautoeject", HIWORD(param));
  1194. break;
  1195. case BURNCFG_ADDTODB:
  1196. g_config->WriteInt(L"cdburnautoadddb", HIWORD(param));
  1197. break;
  1198. case BURNCFG_HIDEVIEW:
  1199. g_config->WriteInt(L"cdburnstatuswnd", !HIWORD(param));
  1200. break;
  1201. }
  1202. break;
  1203. }
  1204. }
  1205. static int CALLBACK WINAPI BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
  1206. {
  1207. switch (uMsg)
  1208. {
  1209. case BFFM_INITIALIZED:
  1210. {
  1211. SendMessageW(hwnd, BFFM_SETSELECTIONW, 1, (LPARAM)WASABI_API_APP->path_getWorkingPath());
  1212. // this is not nice but it fixes the selection not working correctly on all OSes
  1213. EnumChildWindows(hwnd, browseEnumProc, 0);
  1214. }
  1215. }
  1216. return 0;
  1217. }
  1218. wchar_t* BuildFilterList(void)
  1219. {
  1220. static wchar_t fileExtensionsString[128] = {L"*.*"}; // "All files\0*.*\0\0"
  1221. wchar_t *temp=fileExtensionsString+lstrlenW(fileExtensionsString) +1;
  1222. lstrcpynW(temp, WASABI_API_LNGSTRINGW(IDS_ALL_FILES), 128);
  1223. *(temp = temp + lstrlenW(temp) + 1) = 0;
  1224. return fileExtensionsString;
  1225. }
  1226. static void CALLBACK Window_TimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
  1227. {
  1228. HWND hwndList;
  1229. int index, driveIdx;
  1230. wchar_t *pszFileName;
  1231. switch(idEvent)
  1232. {
  1233. case TIMER_NOTIFYINFO_ID:
  1234. KillTimer(hwnd, TIMER_NOTIFYINFO_ID);
  1235. hwndList = GetDlgItem(hwnd, IDC_LIST2);
  1236. driveIdx = LETTERTOINDEX(m_cdrom);
  1237. index = (hwndList) ? (INT)SendMessage(hwndList, LVM_GETNEXTITEM, (WPARAM)-1, (LPARAM)LVNI_FOCUSED) : -1;
  1238. pszFileName = (index >= 0 && index < itemCache[driveIdx].Size) ? itemCache[driveIdx].Items[index].filename : NULL;
  1239. NotifyInfoWindow(hwnd, pszFileName, FALSE);
  1240. break;
  1241. }
  1242. }
  1243. static void ListView_OnItemChanged(HWND hwndDlg, NMLISTVIEW *pnmv)
  1244. {
  1245. if (LVIF_STATE & pnmv->uChanged)
  1246. {
  1247. if ((LVIS_FOCUSED & pnmv->uOldState) != (LVIS_FOCUSED & pnmv->uNewState))
  1248. {
  1249. KillTimer(hwndDlg, TIMER_NOTIFYINFO_ID);
  1250. SetTimer(hwndDlg, TIMER_NOTIFYINFO_ID, TIMER_NOTIFYINFO_DELAY, Window_TimerProc);
  1251. }
  1252. }
  1253. }
  1254. static void Window_OnQueryInfo(HWND hwnd)
  1255. {
  1256. KillTimer(hwnd, TIMER_NOTIFYINFO_ID);
  1257. NotifyInfoWindow(hwnd, NULL, TRUE);
  1258. SetTimer(hwnd, TIMER_NOTIFYINFO_ID, TIMER_NOTIFYINFO_DELAY, Window_TimerProc);
  1259. }
  1260. static void Window_OnOperationCompleted(HWND hwnd, DM_NOTIFY_PARAM *phdr)
  1261. {
  1262. MEDIAINFO mediaInfo;
  1263. if (phdr->cLetter != m_cdrom) return;
  1264. ZeroMemory(&mediaInfo, sizeof(MEDIAINFO));
  1265. mediaInfo.cLetter = m_cdrom;
  1266. switch(phdr->opCode)
  1267. {
  1268. case DMOP_IMAPIINFO:
  1269. if (S_OK == phdr->result)
  1270. {
  1271. DM_IMAPI_PARAM *pIMAPI = (DM_IMAPI_PARAM*)phdr;
  1272. if ((0 != pIMAPI->fMediaType && 0 != pIMAPI->fMediaFlags))
  1273. {
  1274. mediaInfo.bInserted = TRUE;
  1275. if (MEDIA_WRITABLE & pIMAPI->fMediaFlags) mediaInfo.bRecordable = TRUE;
  1276. if (MEDIA_RW & pIMAPI->fMediaFlags) mediaInfo.bRewritable = TRUE;
  1277. if (MEDIA_BLANK & pIMAPI->fMediaFlags) mediaInfo.bBlank = TRUE;
  1278. mediaInfo.nSectorsFree = pIMAPI->ulFreeBlocks;
  1279. mediaInfo.nSectorsUsed = pIMAPI->ulNextWritable;
  1280. }
  1281. }
  1282. else GetMediaInfoFromSonic(&mediaInfo);
  1283. FinishSetStatus(hwnd, &mediaInfo);
  1284. return;
  1285. }
  1286. }
  1287. static INT_PTR CALLBACK DlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1288. {
  1289. INT_PTR a = dialogSkinner.Handle(hwndDlg, uMsg, wParam, lParam); if (a) return a;
  1290. switch (uMsg)
  1291. {
  1292. case WM_SIZE:
  1293. if (wParam != SIZE_MINIMIZED)
  1294. {
  1295. childSizer.Resize(hwndDlg, burnwnd_rlist, sizeof(burnwnd_rlist) / sizeof(burnwnd_rlist[0]));
  1296. }
  1297. break;
  1298. case WM_BURNNOTIFY:
  1299. OnBurnNotify(hwndDlg, (DWORD)wParam, (DWORD)lParam);
  1300. PostMessage(prevWnd, uMsg, wParam, lParam);
  1301. break;
  1302. case WM_INITDIALOG: OnBurnDlgInit(hwndDlg, lParam); return 0;
  1303. case WM_COMMAND:
  1304. switch (LOWORD(wParam))
  1305. {
  1306. // link is dead so disabling for the time being
  1307. /*case IDC_LOGO:
  1308. if (HIWORD(wParam) == BN_CLICKED)
  1309. ShellExecute(hwndDlg, L"open", L"http://estore.sonic.com/redirect.asp?id=spaol110103", NULL, L".", 0);
  1310. break;*/
  1311. case IDC_BURN_OPTS:
  1312. {
  1313. RECT r;
  1314. HMENU menu = GetSubMenu(g_context_menus, 6);
  1315. GetWindowRect((HWND)lParam, &r);
  1316. CheckMenuItem(menu, ID_RIPOPTIONS_RIPPINGSTATUSWINDOW, g_config->ReadInt(L"cdburnstatuswnd", 0) ? MF_CHECKED : MF_UNCHECKED);
  1317. CheckMenuItem(menu, ID_RIPOPTIONS_EJECTCDWHENCOMPLETED, g_config->ReadInt(L"cdburnautoeject", 1) ? MF_CHECKED : MF_UNCHECKED);
  1318. CheckMenuItem(menu, ID_BURNOPTIONS_ADDCDTITLESTOLOCALCDDBCACHE, g_config->ReadInt(L"cdburnautoadddb", 1) ? MF_CHECKED : MF_UNCHECKED);
  1319. CheckMenuItem(menu, ID_RIPOPTIONS_CLOSEVIEWWHENCOMPLETE, g_config->ReadInt(L"cdburnautoclose", 0) ? MF_CHECKED : MF_UNCHECKED);
  1320. int x = Menu_TrackPopup(plugin.hwndLibraryParent, menu,
  1321. TPM_RIGHTBUTTON | TPM_LEFTBUTTON | TPM_BOTTOMALIGN |
  1322. TPM_LEFTALIGN | TPM_NONOTIFY | TPM_RETURNCMD,
  1323. r.left, r.top, hwndDlg, NULL);
  1324. int val = 0, msgid;
  1325. switch (x)
  1326. {
  1327. case ID_RIPOPTIONS_RIPPINGSTATUSWINDOW:
  1328. val = g_config->ReadInt(L"cdburnstatuswnd", 0);
  1329. g_config->WriteInt(L"cdburnstatuswnd", !val);
  1330. msgid = BURNCFG_HIDEVIEW;
  1331. break;
  1332. case ID_RIPOPTIONS_EJECTCDWHENCOMPLETED:
  1333. val = !g_config->ReadInt(L"cdburnautoeject", 1);
  1334. g_config->WriteInt(L"cdburnautoeject", val);
  1335. msgid = BURNCFG_AUTOEJECT;
  1336. break;
  1337. case ID_BURNOPTIONS_ADDCDTITLESTOLOCALCDDBCACHE:
  1338. val = !g_config->ReadInt(L"cdburnautoadddb", 0);
  1339. g_config->WriteInt(L"cdburnautoadddb", val);
  1340. msgid = BURNCFG_ADDTODB;
  1341. break;
  1342. case ID_RIPOPTIONS_CLOSEVIEWWHENCOMPLETE:
  1343. val = !g_config->ReadInt(L"cdburnautoclose", 0);
  1344. g_config->WriteInt(L"cdburnautoclose", val);
  1345. msgid = BURNCFG_AUTOCLOSE;
  1346. break;
  1347. default: msgid = 0; break;
  1348. }
  1349. if (msgid)
  1350. {
  1351. HWND h;
  1352. h = cdburn_FindBurningHWND(m_cdrom);
  1353. if (h)
  1354. {
  1355. PostMessage(h, WM_BURNCONFIGCHANGED, msgid, val);
  1356. if (BURNCFG_HIDEVIEW == msgid) ShowWindow(h, val ? SW_HIDE : SW_SHOW);
  1357. }
  1358. }
  1359. Sleep(100);
  1360. MSG msg;
  1361. while (PeekMessage(&msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)); //eat return
  1362. }
  1363. return 0;
  1364. case IDC_ADD:
  1365. if (DM_MODE_BURNING != DriveManager_GetDriveMode(m_cdrom))
  1366. {
  1367. RECT r;
  1368. GetWindowRect((HWND)lParam, &r);
  1369. int x = Menu_TrackPopup(plugin.hwndLibraryParent, GetSubMenu(g_context_menus, 3),
  1370. TPM_RIGHTBUTTON | TPM_LEFTBUTTON | TPM_BOTTOMALIGN |
  1371. TPM_LEFTALIGN | TPM_NONOTIFY | TPM_RETURNCMD,
  1372. r.left, r.top, hwndDlg, NULL);
  1373. switch (x)
  1374. {
  1375. case ID_BURNADDMENU_FILES:
  1376. {
  1377. OPENFILENAMEW l = {sizeof(l), };
  1378. wchar_t *temp;
  1379. const int len = 256 * 1024 - 128;
  1380. wchar_t *m_extlist = 0;
  1381. m_extlist = (wchar_t*)SendMessage(plugin.hwndWinampParent, WM_WA_IPC, 1, IPC_GET_EXTLISTW);
  1382. if ((int)(INT_PTR)m_extlist == 1) m_extlist = 0;
  1383. temp = (wchar_t *)GlobalAlloc(GPTR, len);
  1384. l.hwndOwner = hwndDlg;
  1385. l.lpstrFilter = m_extlist ? m_extlist : BuildFilterList();
  1386. l.lpstrFile = temp;
  1387. l.nMaxFile = len - 1;
  1388. l.lpstrTitle = WASABI_API_LNGSTRINGW(IDS_ADD_FILES_TO_BURNING_LIST);
  1389. l.lpstrDefExt = L"";
  1390. l.lpstrInitialDir = WASABI_API_APP->path_getWorkingPath();
  1391. l.Flags = OFN_HIDEREADONLY | OFN_EXPLORER | OFN_ALLOWMULTISELECT;
  1392. if (GetOpenFileNameW(&l))
  1393. {
  1394. wchar_t newCurPath[MAX_PATH] = {0};
  1395. GetCurrentDirectoryW(MAX_PATH, newCurPath);
  1396. WASABI_API_APP->path_setWorkingPath(newCurPath);
  1397. if (temp[wcslen(temp) + 1])
  1398. {
  1399. wchar_t buf[MAX_PATH] = {0};
  1400. wchar_t *p = temp;
  1401. wchar_t *path = p;
  1402. p += wcslen(p) + 1;
  1403. while (p && *p)
  1404. {
  1405. if (*path)
  1406. StringCchPrintfW(buf, MAX_PATH, L"%s%s%s", path, path[wcslen(path) - 1] == '\\' ? L"" : L"\\" , p);
  1407. else
  1408. StringCchPrintfW(buf, MAX_PATH, L"%s", p);
  1409. cdburn_appendFile(buf, m_cdrom);
  1410. p += wcslen(p) + 1;
  1411. }
  1412. }
  1413. else
  1414. cdburn_appendFile(temp, m_cdrom);
  1415. }
  1416. GlobalFree(temp);
  1417. if (m_extlist) GlobalFree((HGLOBAL)m_extlist);
  1418. SetStatus(hwndDlg, m_cdrom);
  1419. }
  1420. break;
  1421. case ID_BURNADDMENU_FOLDER:
  1422. {
  1423. BROWSEINFOW bi = {0};
  1424. wchar_t name[MAX_PATH] = {0};
  1425. bi.hwndOwner = hwndDlg;
  1426. bi.pszDisplayName = name;
  1427. bi.lpszTitle = WASABI_API_LNGSTRINGW(IDS_CHOOSE_A_FOLDER_TO_ADD_TO_BURNING_LIST);
  1428. bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE;
  1429. bi.lpfn = BrowseCallbackProc;
  1430. ITEMIDLIST *idlist = SHBrowseForFolderW(&bi);
  1431. if (idlist)
  1432. {
  1433. wchar_t path[MAX_PATH] = {0};
  1434. SHGetPathFromIDListW(idlist, path);
  1435. Shell_Free(idlist);
  1436. cdburn_appendFile(path, m_cdrom);
  1437. SetStatus(hwndDlg, m_cdrom);
  1438. }
  1439. }
  1440. break;
  1441. case ID_BURNADDMENU_CURRENTPLAYLIST:
  1442. {
  1443. int plsize = (int)(INT_PTR)SendMessage(plugin.hwndWinampParent, WM_WA_IPC, 0, IPC_GETLISTLENGTH);
  1444. for (int i = 0;i < plsize;i++)
  1445. {
  1446. wchar_t *name = (wchar_t *)SendMessage(plugin.hwndWinampParent, WM_WA_IPC, i, IPC_GETPLAYLISTFILEW);
  1447. cdburn_appendFile(name, m_cdrom);
  1448. }
  1449. SetStatus(hwndDlg, m_cdrom);
  1450. }
  1451. break;
  1452. }
  1453. Sleep(100);
  1454. MSG msg;
  1455. while (PeekMessage(&msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)); //eat return
  1456. }
  1457. break;
  1458. case IDC_CLEAR:
  1459. if (DM_MODE_BURNING != DriveManager_GetDriveMode(m_cdrom))
  1460. {
  1461. wchar_t title[32] = {0};
  1462. if (MessageBox(hwndDlg, WASABI_API_LNGSTRINGW(IDS_SURE_YOU_WANT_TO_CLEAR_BURNING_LIST),
  1463. WASABI_API_LNGSTRINGW_BUF(IDS_CONFIRMATION,title,32), MB_YESNO) != IDYES)
  1464. break;
  1465. emptyRecordList(&itemCache[LETTERTOINDEX(m_cdrom)]);
  1466. SetStatus(hwndDlg, m_cdrom);
  1467. refreshList();
  1468. }
  1469. break;
  1470. case IDC_CANCEL_BURN:
  1471. case IDC_BURN:
  1472. {
  1473. HWND h;
  1474. if (NULL != (h = cdburn_FindBurningHWND(m_cdrom)))
  1475. {
  1476. PostMessage(h, WM_COMMAND, MAKEWPARAM(IDCANCEL, BN_CLICKED), 0);
  1477. EnableWindow(GetDlgItem(hwndDlg, IDC_BURN), FALSE);
  1478. EnableWindow(GetDlgItem(hwndDlg, IDC_CANCEL_BURN), FALSE);
  1479. }
  1480. else doBurnDialog(hwndDlg);
  1481. }
  1482. break;
  1483. case IDC_BTN_SHOWINFO:
  1484. switch(HIWORD(wParam))
  1485. {
  1486. case BN_CLICKED: SendMessageW(GetParent(hwndDlg), WM_COMMAND, wParam, lParam); break;
  1487. }
  1488. break;
  1489. }
  1490. break;
  1491. case WM_CONTEXTMENU:
  1492. {
  1493. if (DM_MODE_BURNING == DriveManager_GetDriveMode(m_cdrom) || m_statuslist.GetCount() == 0) return 0;
  1494. HMENU menu = GetSubMenu(g_context_menus, 4);
  1495. POINT pt = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
  1496. if (pt.x == -1 || pt.y == -1) // x and y are -1 if the user invoked a shift-f10 popup menu
  1497. {
  1498. RECT itemRect = {0};
  1499. int selected = m_statuslist.GetNextSelected();
  1500. if (selected != -1) // if something is selected we'll drop the menu from there
  1501. {
  1502. m_statuslist.GetItemRect(selected, &itemRect);
  1503. ClientToScreen(m_statuslist.getwnd(), (POINT *)&itemRect);
  1504. }
  1505. else // otherwise we'll drop it from the top-left corner of the listview, adjusting for the header location
  1506. {
  1507. GetWindowRect(m_statuslist.getwnd(), &itemRect);
  1508. HWND hHeader = (HWND)SNDMSG((HWND)wParam, LVM_GETHEADER, 0, 0L);
  1509. RECT headerRect;
  1510. if ((WS_VISIBLE & GetWindowLongPtr(hHeader, GWL_STYLE)) && GetWindowRect(hHeader, &headerRect))
  1511. {
  1512. itemRect.top += (headerRect.bottom - headerRect.top);
  1513. }
  1514. }
  1515. pt.x = itemRect.left;
  1516. pt.y = itemRect.top;
  1517. }
  1518. HWND hHeader = (HWND)SNDMSG((HWND)wParam, LVM_GETHEADER, 0, 0L);
  1519. RECT headerRect;
  1520. if (0 == (WS_VISIBLE & GetWindowLongPtr(hHeader, GWL_STYLE)) || FALSE == GetWindowRect(hHeader, &headerRect))
  1521. {
  1522. SetRectEmpty(&headerRect);
  1523. }
  1524. if (FALSE != PtInRect(&headerRect, pt))
  1525. {
  1526. return 0;
  1527. }
  1528. int r = Menu_TrackPopup(plugin.hwndLibraryParent, menu,
  1529. TPM_RETURNCMD | TPM_RIGHTBUTTON | TPM_LEFTBUTTON | TPM_NONOTIFY,
  1530. pt.x, pt.y, hwndDlg, NULL);
  1531. switch (r)
  1532. {
  1533. case ID_BURNCONTEXTMENU_PLAYSELECTEDITEMS:
  1534. playSelectedItems(hwndDlg, 0);
  1535. break;
  1536. case ID_BURNCONTEXTMENU_ENQUEUESELECTEDITEMS:
  1537. playSelectedItems(hwndDlg, 1);
  1538. break;
  1539. case ID_BURNCONTEXTMENU_SELECTALL:
  1540. selectAll();
  1541. break;
  1542. case ID_BURNCONTEXTMENU_REMOVESELECTEDITEMS:
  1543. if (DM_MODE_BURNING != DriveManager_GetDriveMode(m_cdrom)) deleteSelectedItems(hwndDlg, m_cdrom);
  1544. break;
  1545. case ID_BURNCONTEXTMENU_BURN:
  1546. doBurnDialog(hwndDlg);
  1547. break;
  1548. case ID_BURNCONTEXTMENU_MOVESELECTEDITEMSUP:
  1549. moveSelItemsUp();
  1550. break;
  1551. case ID_BURNCONTEXTMENU_MOVESELECTEDITEMSDOWN:
  1552. moveSelItemsDown();
  1553. break;
  1554. }
  1555. Sleep(100);
  1556. MSG msg;
  1557. while (PeekMessage(&msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)); //eat return
  1558. return 1;
  1559. }
  1560. case WM_NOTIFY:
  1561. {
  1562. LPNMHDR l = (LPNMHDR)lParam;
  1563. if (l->idFrom == IDC_LIST2)
  1564. {
  1565. if (l->code == LVN_KEYDOWN)
  1566. {
  1567. LPNMLVKEYDOWN pnkd = (LPNMLVKEYDOWN) lParam;
  1568. switch (pnkd->wVKey)
  1569. {
  1570. case 38: //up
  1571. if (GetAsyncKeyState(VK_LMENU))
  1572. {
  1573. moveSelItemsUp();
  1574. return 1;
  1575. }
  1576. break;
  1577. case 40: //down
  1578. if (GetAsyncKeyState(VK_LMENU))
  1579. {
  1580. moveSelItemsDown();
  1581. return 1;
  1582. }
  1583. break;
  1584. case 46: //delete
  1585. if (DM_MODE_BURNING != DriveManager_GetDriveMode(m_cdrom)) deleteSelectedItems(hwndDlg, m_cdrom);
  1586. break;
  1587. case 'A':
  1588. if (GetAsyncKeyState(VK_CONTROL))
  1589. selectAll();
  1590. break;
  1591. }
  1592. }
  1593. else if (l->code == NM_DBLCLK)
  1594. {
  1595. if (DM_MODE_BURNING == DriveManager_GetDriveMode(m_cdrom)) return 0;
  1596. playSelectedItems(hwndDlg, (!!g_config->ReadInt(L"enqueuedef", 0)) ^(!!(GetAsyncKeyState(VK_SHIFT)&0x8000)));
  1597. }
  1598. else if (l->code == NM_RETURN)
  1599. {
  1600. if (DM_MODE_BURNING == DriveManager_GetDriveMode(m_cdrom)) return 0;
  1601. playSelectedItems(hwndDlg, 0 ^(!!(GetAsyncKeyState(VK_SHIFT)&0x8000)));
  1602. }
  1603. else if (l->code == LVN_GETDISPINFO)
  1604. {
  1605. NMLVDISPINFO *lpdi = (NMLVDISPINFO*) lParam;
  1606. int item = lpdi->item.iItem;
  1607. int idx = LETTERTOINDEX(m_cdrom);
  1608. if (item < 0 || item >= itemCache[idx].Size) return 0;
  1609. itemRecordW *thisitem = itemCache[idx].Items + item;
  1610. if (lpdi->item.mask & (LVIF_TEXT | /*LVIF_IMAGE*/0)) // we can always do images too :)
  1611. {
  1612. if (lpdi->item.mask & LVIF_TEXT)
  1613. {
  1614. wchar_t tmpbuf[128] = {0};
  1615. wchar_t *nameptr = 0;
  1616. switch (lpdi->item.iSubItem)
  1617. {
  1618. case 0:
  1619. //track #
  1620. StringCchPrintfW(tmpbuf, 128, L"%d", item + 1);
  1621. nameptr = tmpbuf;
  1622. break;
  1623. case 1:
  1624. //title
  1625. lstrcpynW(tmpbuf, thisitem->title, 128);
  1626. nameptr = tmpbuf;
  1627. break;
  1628. case 2:
  1629. //length
  1630. StringCchPrintfW(tmpbuf, 128, L"%01d:%02d", thisitem->length / 60, thisitem->length % 60);
  1631. nameptr = tmpbuf;
  1632. break;
  1633. case 3:
  1634. DWORD state = (DWORD) SendMessage(m_burning_other_wnd, WM_BURNGETITEMSTATUS, BURNSTATUS_STATE, (LPARAM)item);
  1635. switch (state)
  1636. {
  1637. case BURNERITEM_BURNING:
  1638. case BURNERITEM_DECODING:
  1639. StringCchPrintfW(tmpbuf, 128, L"%s (%d%%)",
  1640. WASABI_API_LNGSTRINGW((BURNERITEM_BURNING == state) ? IDS_BURNING_ : IDS_PREPARING),
  1641. (DWORD)SendMessage(m_burning_other_wnd, WM_BURNGETITEMSTATUS, BURNSTATUS_PROGRESS, (LPARAM)item));
  1642. nameptr = tmpbuf;
  1643. break;
  1644. case BURNERITEM_SUCCESS: break;
  1645. case BURNERITEM_BURNED:
  1646. nameptr = WASABI_API_LNGSTRINGW_BUF(IDS_FINISHED,tmpbuf,128);
  1647. break;
  1648. case BURNERITEM_DECODED:
  1649. nameptr = WASABI_API_LNGSTRINGW_BUF(IDS_PREPARED,tmpbuf,128);
  1650. break;
  1651. case BURNERITEM_SKIPPED:
  1652. nameptr = WASABI_API_LNGSTRINGW_BUF(IDS_SKIPPED,tmpbuf,128);
  1653. break;
  1654. case BURNERITEM_READY:
  1655. nameptr = WASABI_API_LNGSTRINGW_BUF(IDS_SCHEDULED,tmpbuf,128);
  1656. break;
  1657. case BURNERITEM_LICENSING:
  1658. nameptr = WASABI_API_LNGSTRINGW_BUF(IDS_CHECKING_LICENSE,tmpbuf,128);
  1659. break;
  1660. case BURNERITEM_LICENSED:
  1661. nameptr = WASABI_API_LNGSTRINGW_BUF(IDS_LICENSED,tmpbuf,128);
  1662. break;
  1663. case BURNERITEM_ABORTED:
  1664. nameptr = WASABI_API_LNGSTRINGW_BUF(IDS_CANCELLED,tmpbuf,128);
  1665. break;
  1666. case BURNERITEM_FAILED:
  1667. nameptr = WASABI_API_LNGSTRINGW_BUF(IDS_FAILED,tmpbuf,128);
  1668. break;
  1669. case BURNERITEM_CANCELING:
  1670. nameptr = WASABI_API_LNGSTRINGW_BUF(IDS_CANCELLING,tmpbuf,128);
  1671. break;
  1672. case BURNERITEM_BADFILENAME:
  1673. nameptr = WASABI_API_LNGSTRINGW_BUF(IDS_BAD_FILENAME,tmpbuf,128);
  1674. break;
  1675. case BURNERITEM_UNABLEOPENFILE:
  1676. nameptr = WASABI_API_LNGSTRINGW_BUF(IDS_UNABLE_TO_OPEN_FILE,tmpbuf,128);
  1677. break;
  1678. case BURNERITEM_WRITEERROR:
  1679. nameptr = WASABI_API_LNGSTRINGW_BUF(IDS_CACHE_WRITE_FAILED,tmpbuf,128);
  1680. break;
  1681. case BURNERITEM_DECODEERROR:
  1682. nameptr = WASABI_API_LNGSTRINGW_BUF(IDS_UNABLE_TO_FIND_DECODER,tmpbuf,128);
  1683. break;
  1684. case BURNERITEM_ADDSTREAMFAILED:
  1685. nameptr = WASABI_API_LNGSTRINGW_BUF(IDS_CANNOT_ADD_TO_THE_DISC,tmpbuf,128);
  1686. break;
  1687. case BURNERITEM_READSTREAMERROR:
  1688. nameptr = WASABI_API_LNGSTRINGW_BUF(IDS_CACHE_READ_FAILED,tmpbuf,128);
  1689. break;
  1690. default:
  1691. nameptr = WASABI_API_LNGSTRINGW_BUF(IDS_UNKNOWN_ERROR,tmpbuf,128);
  1692. break;
  1693. }
  1694. //status
  1695. break;
  1696. }
  1697. if (nameptr)
  1698. lstrcpynW(lpdi->item.pszText, nameptr, lpdi->item.cchTextMax);
  1699. else
  1700. lpdi->item.pszText[0] = 0;
  1701. }
  1702. }
  1703. return 0;
  1704. }
  1705. else if (l->code == LVN_BEGINDRAG)
  1706. {
  1707. SetCapture(hwndDlg);
  1708. m_dragging = 1;
  1709. LPNMLISTVIEW nlv = (LPNMLISTVIEW)lParam;
  1710. m_drag_item = nlv->iItem;
  1711. }
  1712. else if (l->code == LVN_ITEMCHANGED) ListView_OnItemChanged(hwndDlg, (NMLISTVIEW*)l);
  1713. }
  1714. }
  1715. break;
  1716. case WM_MOUSEMOVE:
  1717. if (m_dragging)
  1718. {
  1719. POINT p;
  1720. p.x = GET_X_LPARAM(lParam);
  1721. p.y = GET_Y_LPARAM(lParam);
  1722. ClientToScreen(hwndDlg, &p);
  1723. ScreenToClient(m_statuslist.getwnd(), &p);
  1724. int i = m_statuslist.FindItemByPoint(p.x, p.y);
  1725. if (i != -1 && i != m_drag_item)
  1726. {
  1727. if (i > m_drag_item)
  1728. {
  1729. for (int j = 0;j < (i - m_drag_item);j++)
  1730. moveSelItemsDown();
  1731. }
  1732. else
  1733. {
  1734. for (int j = 0;j < (m_drag_item - i);j++)
  1735. moveSelItemsUp();
  1736. }
  1737. m_drag_item = i;
  1738. }
  1739. }
  1740. break;
  1741. case WM_LBUTTONUP:
  1742. if (GetCapture() == hwndDlg)
  1743. {
  1744. ReleaseCapture();
  1745. m_dragging = 0;
  1746. }
  1747. break;
  1748. case WM_DESTROY:
  1749. if (m_statuslist.getwnd())
  1750. {
  1751. g_view_metaconf->WriteInt(L"col_track", m_statuslist.GetColumnWidth(0));
  1752. g_view_metaconf->WriteInt(L"col_title", m_statuslist.GetColumnWidth(1));
  1753. g_view_metaconf->WriteInt(L"col_len", m_statuslist.GetColumnWidth(2));
  1754. g_view_metaconf->WriteInt(L"col_status", m_statuslist.GetColumnWidth(3));
  1755. }
  1756. if (m_burning_other_wnd && IsWindow(m_burning_other_wnd))
  1757. {
  1758. PostMessage(m_burning_other_wnd, WM_BURNUPDATEOWNER, 0, (LPARAM)prevWnd);
  1759. prevWnd = NULL;
  1760. }
  1761. m_hwndstatus = 0;
  1762. if (hPLFont)
  1763. {
  1764. DeleteObject(hPLFont);
  1765. hPLFont = NULL;
  1766. }
  1767. {
  1768. HANDLE hPrev = (HANDLE) SendDlgItemMessage(hwndDlg,IDC_LOGO,STM_SETIMAGE,IMAGE_BITMAP, 0L);
  1769. if (hPrev) DeleteObject(hPrev);
  1770. }
  1771. return 0;
  1772. case WM_ML_CHILDIPC:
  1773. if (lParam == ML_CHILDIPC_DROPITEM && wParam)
  1774. {
  1775. mlDropItemStruct *dis = (mlDropItemStruct *)wParam;
  1776. if (DM_MODE_BURNING == DriveManager_GetDriveMode(m_cdrom))
  1777. {
  1778. dis->result = -1;
  1779. return 0;
  1780. }
  1781. if (dis->type != ML_TYPE_ITEMRECORDLISTW && dis->type != ML_TYPE_ITEMRECORDLIST &&
  1782. dis->type != ML_TYPE_FILENAMES && dis->type != ML_TYPE_FILENAMESW)
  1783. {
  1784. dis->result = -1;
  1785. }
  1786. else
  1787. {
  1788. if (dis->data)
  1789. {
  1790. dis->result = 1;
  1791. if (dis->type == ML_TYPE_ITEMRECORDLIST)
  1792. {
  1793. itemRecordList *obj = (itemRecordList *)dis->data;
  1794. cdburn_appendItemRecord(obj, m_cdrom);
  1795. }
  1796. else if (dis->type == ML_TYPE_ITEMRECORDLISTW)
  1797. {
  1798. itemRecordListW *obj = (itemRecordListW *)dis->data;
  1799. cdburn_appendItemRecord(obj, m_cdrom);
  1800. }
  1801. else if (dis->type == ML_TYPE_FILENAMES) // playlist
  1802. {
  1803. char *p = (char*)dis->data;
  1804. while (p && *p)
  1805. {
  1806. cdburn_appendFile(p, m_cdrom);
  1807. p += strlen(p) + 1;
  1808. }
  1809. }
  1810. else if (dis->type == ML_TYPE_FILENAMESW)
  1811. {
  1812. wchar_t *p = (wchar_t*)dis->data;
  1813. while (p && *p)
  1814. {
  1815. cdburn_appendFile(p, m_cdrom);
  1816. p += wcslen(p) + 1;
  1817. }
  1818. }
  1819. }
  1820. }
  1821. }
  1822. return 0;
  1823. case WM_DROPFILES:
  1824. {
  1825. char temp[2048] = {0};
  1826. HDROP h = (HDROP) wParam;
  1827. int y = DragQueryFileA(h, 0xffffffff, temp, sizeof(temp));
  1828. if (DM_MODE_BURNING == DriveManager_GetDriveMode(m_cdrom))
  1829. {
  1830. // MessageBoxA(hwndDlg,"Cannot add files while burning","CD Burner",MB_OK);
  1831. }
  1832. else for (int x = 0; x < y; x ++)
  1833. {
  1834. DragQueryFileA(h, x, temp, sizeof(temp));
  1835. cdburn_appendFile(temp, m_cdrom);
  1836. }
  1837. DragFinish(h);
  1838. }
  1839. return 0;
  1840. case WM_PAINT:
  1841. {
  1842. int tab[] = { IDC_LIST2 | DCW_SUNKENBORDER, IDC_LOGO | DCW_SUNKENBORDER};
  1843. dialogSkinner.Draw(hwndDlg, tab, 2);
  1844. }
  1845. return 0;
  1846. case WM_ERASEBKGND: return 1; //handled by WADlg_DrawChildWindowBorders in WM_PAINT
  1847. case WM_QUERYFILEINFO: Window_OnQueryInfo(hwndDlg); break;
  1848. case WM_EX_OPCOMPLETED: Window_OnOperationCompleted(hwndDlg, (DM_NOTIFY_PARAM*)lParam);
  1849. }
  1850. return FALSE;
  1851. }
  1852. static HWND BurnAddStatus_wnd;
  1853. static BOOL CALLBACK BurnAddStatus_proc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1854. {
  1855. if (uMsg == WM_CLOSE)
  1856. DestroyWindow(hwndDlg);
  1857. return 0;
  1858. }
  1859. void BurnAddStatus_Create(int num)
  1860. {
  1861. if (BurnAddStatus_wnd && IsWindow(BurnAddStatus_wnd)) DestroyWindow(BurnAddStatus_wnd);
  1862. BurnAddStatus_wnd = WASABI_API_CREATEDIALOGW(IDD_BURN_ADD_STATUS, plugin.hwndLibraryParent, BurnAddStatus_proc);
  1863. if (!BurnAddStatus_wnd) return ;
  1864. SetTimer(BurnAddStatus_wnd, 1, 100, NULL);
  1865. SendDlgItemMessage(BurnAddStatus_wnd, IDC_PROGRESS1, PBM_SETRANGE, 0, MAKELPARAM(0, num));
  1866. unsigned int start_t = GetTickCount();
  1867. if (start_t >= 0xffffff00) start_t = 0;
  1868. MSG msg;
  1869. while (GetTickCount() < start_t + 100 && GetMessage(&msg, NULL, 0, 0))
  1870. {
  1871. TranslateMessage(&msg);
  1872. DispatchMessage(&msg);
  1873. }
  1874. }
  1875. void BurnAddStatus_Step(itemRecordListW *items)
  1876. {
  1877. if (!BurnAddStatus_wnd || !items || items && !items->Size || items && !items->Items) return ;
  1878. SendDlgItemMessage(BurnAddStatus_wnd, IDC_PROGRESS1, PBM_DELTAPOS, 1, 0);
  1879. int l = 0;
  1880. for (int i = 0;i < items->Size;i++)
  1881. {
  1882. l += items->Items[i].length;
  1883. }
  1884. wchar_t buf[512] = {0};
  1885. StringCchPrintf(buf, 512, WASABI_API_LNGSTRINGW(IDS_ADDING_TRACKS_TO_BURNER_TOTAL_LENGTH_X), l / 60, l % 60);
  1886. SetDlgItemText(BurnAddStatus_wnd, IDC_STAT, buf);
  1887. }
  1888. void BurnAddStatus_Done()
  1889. {
  1890. if (!BurnAddStatus_wnd) return ;
  1891. unsigned int start_t = GetTickCount();
  1892. if (start_t >= 0xffffff00) start_t = 0;
  1893. MSG msg;
  1894. while (GetTickCount() < start_t + 1000 && IsWindow(BurnAddStatus_wnd) && GetMessage(&msg, NULL, 0, 0))
  1895. {
  1896. TranslateMessage(&msg);
  1897. DispatchMessage(&msg);
  1898. }
  1899. DestroyWindow(BurnAddStatus_wnd);
  1900. BurnAddStatus_wnd = 0;
  1901. }
  1902. static bool cdrFound(char letter)
  1903. {
  1904. wchar_t name[]= L"cda://X.cda";
  1905. wchar_t info[16] = L"";
  1906. name[6] = letter;
  1907. getFileInfoW(name, L"cdtype", info, sizeof(info)/sizeof(wchar_t));
  1908. return !lstrcmpW(info, L"CDR") || !lstrcmpW(info, L"CDRW");
  1909. }
  1910. static char m_burnwait_letter;
  1911. static BOOL CALLBACK BurnWaitProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1912. {
  1913. switch (uMsg)
  1914. {
  1915. case WM_INITDIALOG:
  1916. SetTimer(hwndDlg, 1, 2000, NULL);
  1917. {
  1918. wchar_t buf[512] = {0};
  1919. StringCchPrintf(buf, 512, WASABI_API_LNGSTRINGW(IDS_PLEASE_INSERT_BLANK_RECORDABLE_CD), toupper(m_burnwait_letter));
  1920. SetDlgItemText(hwndDlg, IDC_TEXT, buf);
  1921. }
  1922. return 0;
  1923. case WM_COMMAND:
  1924. if (LOWORD(wParam) == IDCANCEL) EndDialog(hwndDlg, 1);
  1925. return 0;
  1926. case WM_TIMER:
  1927. if (cdrFound(m_burnwait_letter)) EndDialog(hwndDlg, 0);
  1928. return 0;
  1929. }
  1930. return 0;
  1931. }
  1932. int Burn_WaitForCDR(HWND hwndParent, char driveletter) // returns 0 on CD-R found, 1 on cancel
  1933. {
  1934. CHAR cMode;
  1935. if (!driveletter) return 1;
  1936. cMode = DriveManager_GetDriveMode(driveletter);
  1937. if (DM_MODE_BURNING == cMode || DM_MODE_RIPPING == cMode)
  1938. {
  1939. return 1; // if burning or ripping, don't fuck with it
  1940. }
  1941. if (cdrFound(driveletter)) return 0;
  1942. if (m_burnwait_letter) return 1;
  1943. m_burnwait_letter = (char)toupper(driveletter);
  1944. int x = (int)(INT_PTR)WASABI_API_DIALOGBOXW(IDD_WAITFORCDR, hwndParent, BurnWaitProc);
  1945. m_burnwait_letter = 0;
  1946. return x;
  1947. }