1
0

prefs.cpp 54 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541
  1. #include "../Winamp/buildType.h"
  2. #include "api__ml_pmp.h"
  3. #include "main.h"
  4. #include "../ml_wire/ifc_podcast.h"
  5. #include "DeviceView.h"
  6. #include "nu/AutoWide.h"
  7. #include "transcoder_imp.h"
  8. #include "nu/listview.h"
  9. #include "nu/AutoLock.h"
  10. #include <Commctrl.h>
  11. #include <shlwapi.h>
  12. #include <strsafe.h>
  13. #include <api/syscb/callbacks/browsercb.h>
  14. #if defined (_WIN64)
  15. #include "../Elevator/IFileTypeRegistrar_64.h"
  16. #else
  17. #include "../Elevator/IFileTypeRegistrar_32.h"
  18. #endif
  19. extern winampMediaLibraryPlugin plugin;
  20. extern DeviceView * currentViewedDevice;
  21. extern C_ItemList m_plugins;
  22. extern C_Config * global_config;
  23. extern C_ItemList devices;
  24. extern HWND hwndMediaView;
  25. static void link_handledraw(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
  26. void link_startsubclass(HWND hwndDlg, UINT id);
  27. INT_PTR CALLBACK global_config_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam);
  28. INT_PTR CALLBACK config_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam);
  29. static INT_PTR CALLBACK config_dlgproc_sync(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam);
  30. static INT_PTR CALLBACK config_dlgproc_cloud_sync(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam);
  31. static INT_PTR CALLBACK config_dlgproc_podcast_sync(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam);
  32. static INT_PTR CALLBACK config_dlgproc_autofill(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam);
  33. static INT_PTR CALLBACK config_dlgproc_transcode(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam);
  34. static INT_PTR CALLBACK config_dlgproc_mediaview(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam);
  35. static INT_PTR CALLBACK config_dlgproc_cloud_mediaview(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam);
  36. INT_PTR CALLBACK config_dlgproc_plugins(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam);
  37. void myOpenURLWithFallback(HWND hwnd, wchar_t *loc, wchar_t *fallbackLoc);
  38. HWND m_hwndTab = NULL, m_hwndTabDisplay = NULL;
  39. int g_prefs_openpage=0;
  40. static C_Config * config;
  41. DeviceView * configDevice;
  42. enum {
  43. SYNC_PREF_IDX = 0,
  44. PODSYNC_PREF_IDX,
  45. AUTOFILL_PREF_IDX,
  46. TRANS_PREF_IDX,
  47. MEDIAVIEW_PREF_IDX
  48. };
  49. static pref_tab tabs[] = {
  50. {L"",IDD_CONFIG_SYNC,config_dlgproc_sync,0},
  51. {L"",IDD_CONFIG_PODCAST_SYNC,config_dlgproc_podcast_sync,0},
  52. {L"",IDD_CONFIG_AUTOFILL,config_dlgproc_autofill,0},
  53. {L"",IDD_CONFIG_TRANSCODE,config_dlgproc_transcode,0},
  54. {L"",IDD_CONFIG_MEDIAVIEW,config_dlgproc_mediaview,0},
  55. {L"",0,0,0}, // extra config for plugins
  56. };
  57. static void config_tab_init(HWND tab,HWND m_hwndDlg)
  58. {
  59. RECT r;
  60. GetWindowRect(m_hwndTab,&r);
  61. TabCtrl_AdjustRect(m_hwndTab,FALSE,&r);
  62. MapWindowPoints(NULL,m_hwndDlg,(LPPOINT)&r,2);
  63. SetWindowPos(tab,HWND_TOP,r.left,r.top,r.right-r.left,r.bottom-r.top,SWP_NOACTIVATE);
  64. if(!SendMessage(plugin.hwndWinampParent,WM_WA_IPC,IPC_ISWINTHEMEPRESENT,IPC_USE_UXTHEME_FUNC))
  65. SendMessage(plugin.hwndWinampParent,WM_WA_IPC,(WPARAM)tab,IPC_USE_UXTHEME_FUNC);
  66. }
  67. HWND OnSelChanged(HWND hwndDlg, HWND external = NULL, DeviceView *dev = NULL)
  68. {
  69. static prefsParam p;
  70. int sel=(!external ? TabCtrl_GetCurSel(m_hwndTab) : MEDIAVIEW_PREF_IDX);
  71. if (!external)
  72. {
  73. g_prefs_openpage=sel;
  74. if(m_hwndTabDisplay!=NULL)
  75. DestroyWindow(m_hwndTabDisplay);
  76. p.config_tab_init = config_tab_init;
  77. p.dev = configDevice->dev;
  78. p.parent = hwndDlg;
  79. // copes with the Transcoding tab being hidden
  80. if (sel >= TRANS_PREF_IDX && tabs[TRANS_PREF_IDX].title[0] == 0) sel++;
  81. }
  82. else
  83. {
  84. configDevice = dev;
  85. config = dev->config;
  86. p.config_tab_init = config_tab_init;
  87. p.dev = dev->dev;
  88. p.parent = hwndDlg;
  89. }
  90. // copes with a cloud device which doesn't need podcast sync and autofill
  91. // as well as factoring in the transcoding page needing to be hidden, etc
  92. if (configDevice->isCloudDevice)
  93. {
  94. if (!external && (sel >= SYNC_PREF_IDX)) sel += (3 + (tabs[TRANS_PREF_IDX].title[0] == 0));
  95. if (sel == MEDIAVIEW_PREF_IDX)
  96. {
  97. tabs[sel].res_id = IDD_CONFIG_CLOUD_MEDIAVIEW;
  98. tabs[sel].dlg_proc = config_dlgproc_cloud_mediaview;
  99. }
  100. }
  101. else
  102. {
  103. if (sel == SYNC_PREF_IDX)
  104. {
  105. tabs[sel].res_id = IDD_CONFIG_SYNC;
  106. tabs[sel].dlg_proc = config_dlgproc_sync;
  107. }
  108. if (sel == MEDIAVIEW_PREF_IDX)
  109. {
  110. tabs[sel].res_id = IDD_CONFIG_MEDIAVIEW;
  111. tabs[sel].dlg_proc = config_dlgproc_mediaview;
  112. }
  113. }
  114. if(!tabs[sel].hinst)
  115. m_hwndTabDisplay=WASABI_API_CREATEDIALOGPARAMW(tabs[sel].res_id, hwndDlg, tabs[sel].dlg_proc, (LPARAM)&p);
  116. else
  117. m_hwndTabDisplay=WASABI_API_LNG->CreateLDialogParamW(tabs[sel].hinst, tabs[sel].hinst, tabs[sel].res_id, hwndDlg, tabs[sel].dlg_proc, (LPARAM)&p);
  118. if (!external)
  119. {
  120. RECT r;
  121. GetClientRect(m_hwndTab, &r);
  122. TabCtrl_AdjustRect(m_hwndTab, FALSE, &r);
  123. SetWindowPos(m_hwndTabDisplay, HWND_TOP, r.left, r.top, r.right - r.left, r.bottom - r.top, SWP_NOACTIVATE | SWP_SHOWWINDOW);
  124. }
  125. return m_hwndTabDisplay;
  126. }
  127. void Shell_Free(void *p) {
  128. IMalloc *m = NULL;
  129. if (SUCCEEDED(SHGetMalloc(&m)) && m)
  130. {
  131. m->Free(p);
  132. }
  133. }
  134. wchar_t* GetDefaultSaveToFolder(wchar_t* path_to_store)
  135. {
  136. if(FAILED(SHGetFolderPath(NULL, CSIDL_MYMUSIC, NULL, SHGFP_TYPE_CURRENT, path_to_store)))
  137. {
  138. if(FAILED(SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, path_to_store)))
  139. {
  140. // and if that all fails then do a reasonable default
  141. lstrcpyn(path_to_store, L"C:\\My Music", MAX_PATH);
  142. }
  143. // if there's no valid My Music folder (typically win2k) then default to %my_documents%\my music
  144. else
  145. {
  146. PathCombine(path_to_store, path_to_store, L"My Music");
  147. }
  148. }
  149. return path_to_store;
  150. }
  151. BOOL CALLBACK browseEnumProc(HWND hwnd, LPARAM lParam)
  152. {
  153. wchar_t cl[32] = {0};
  154. GetClassNameW(hwnd, cl, ARRAYSIZE(cl));
  155. if (!lstrcmpiW(cl, WC_TREEVIEW))
  156. {
  157. PostMessage(hwnd, TVM_ENSUREVISIBLE, 0, (LPARAM)TreeView_GetSelection(hwnd));
  158. return FALSE;
  159. }
  160. return TRUE;
  161. }
  162. int CALLBACK WINAPI BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
  163. {
  164. if(uMsg == BFFM_INITIALIZED)
  165. {
  166. wchar_t m_def_extract_path[MAX_PATH] = L"C:\\My Music";
  167. SendMessageW(hwnd, BFFM_SETSELECTIONW, 1, (LPARAM)global_config->ReadString(L"extractpath", GetDefaultSaveToFolder(m_def_extract_path)));
  168. // this is not nice but it fixes the selection not working correctly on all OSes
  169. EnumChildWindows(hwnd, browseEnumProc, 0);
  170. }
  171. return 0;
  172. }
  173. extern void doFormatFileName(wchar_t out[MAX_PATH], wchar_t *fmt, int trackno, wchar_t *artist, wchar_t *album, wchar_t *title, wchar_t *genre, wchar_t *year, wchar_t *trackartist);
  174. INT_PTR CALLBACK global_config_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam) {
  175. wchar_t m_def_extract_path[MAX_PATH] = L"C:\\My Music";
  176. switch (uMsg)
  177. {
  178. case WM_INITDIALOG:
  179. {
  180. wchar_t m_def_filename_fmt[] = L"<Artist> - <Album>\\## - <Trackartist> - <Title>";
  181. GetDefaultSaveToFolder(m_def_extract_path);
  182. if (global_config->ReadInt(L"extractusecdrip", 1)) CheckDlgButton(hwndDlg, IDC_CHECK_USECDRIP, BST_CHECKED);
  183. SendDlgItemMessage(hwndDlg, IDC_DESTPATH, EM_SETLIMITTEXT, MAX_PATH, 0);
  184. SetDlgItemText(hwndDlg, IDC_DESTPATH, global_config->ReadString(L"extractpath", m_def_extract_path));
  185. SetDlgItemText(hwndDlg, IDC_FILENAMEFMT, global_config->ReadString(L"extractfmt2", m_def_filename_fmt));
  186. SendMessage(hwndDlg,WM_USER,0,0);
  187. }
  188. break;
  189. case WM_USER:
  190. {
  191. BOOL enabled = !IsDlgButtonChecked(hwndDlg, IDC_CHECK_USECDRIP);
  192. EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC_1),enabled);
  193. EnableWindow(GetDlgItem(hwndDlg,IDC_DESTPATH),enabled);
  194. EnableWindow(GetDlgItem(hwndDlg,IDC_BUTTON1),enabled);
  195. EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC_2),enabled);
  196. EnableWindow(GetDlgItem(hwndDlg,IDC_BUTTON2),enabled);
  197. EnableWindow(GetDlgItem(hwndDlg,IDC_FILENAMEFMT),enabled);
  198. EnableWindow(GetDlgItem(hwndDlg,IDC_FMTOUT),enabled);
  199. }
  200. break;
  201. case WM_COMMAND:
  202. switch (LOWORD(wParam))
  203. {
  204. case IDC_DESTPATH:
  205. if (HIWORD(wParam) == EN_CHANGE)
  206. {
  207. wchar_t buf[1024] = {0};
  208. GetDlgItemText(hwndDlg, IDC_DESTPATH, buf, 1024);
  209. global_config->WriteString(L"extractpath", buf);
  210. }
  211. return 0;
  212. case IDC_CHECK_USECDRIP:
  213. {
  214. global_config->WriteInt(L"extractusecdrip", !!IsDlgButtonChecked(hwndDlg, IDC_CHECK_USECDRIP));
  215. SendMessage(hwndDlg,WM_USER,0,0);
  216. }
  217. break;
  218. // run through...
  219. case IDC_FILENAMEFMT:
  220. if (HIWORD(wParam) == EN_CHANGE)
  221. {
  222. wchar_t buf[1024] = {0};
  223. GetDlgItemText(hwndDlg, IDC_FILENAMEFMT, buf, 1024);
  224. if(LOWORD(wParam) == IDC_FILENAMEFMT) global_config->WriteString(L"extractfmt2", buf);
  225. wchar_t str[MAX_PATH] = {0};
  226. doFormatFileName(WASABI_API_LNGSTRINGW_BUF(IDS_EXAMPLE_FORMATTING_STRING,str,MAX_PATH),
  227. buf, 10, L"U2", L"The Joshua Tree", L"Exit", L"Rock", L"1987", L"U2");
  228. wchar_t fmt[5]=L"mp3";
  229. StringCchCat(str, MAX_PATH, L".");
  230. StringCchCat(str, MAX_PATH, fmt);
  231. SetDlgItemText(hwndDlg, IDC_FMTOUT, str);
  232. }
  233. return 0;
  234. case IDC_BUTTON1:
  235. {
  236. //browse for folder
  237. BROWSEINFO bi = {0};
  238. wchar_t name[MAX_PATH] = {0};
  239. bi.hwndOwner = hwndDlg;
  240. bi.pidlRoot = NULL;
  241. bi.pszDisplayName = name;
  242. bi.lpszTitle = WASABI_API_LNGSTRINGW(IDS_CHOOSE_A_FOLDER);
  243. bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE;
  244. bi.lpfn = BrowseCallbackProc;
  245. ITEMIDLIST *idlist = SHBrowseForFolder(&bi);
  246. if (idlist)
  247. {
  248. wchar_t path[MAX_PATH] = {0};
  249. SHGetPathFromIDList( idlist, path );
  250. Shell_Free(idlist);
  251. global_config->WriteString(L"extractpath", path);
  252. SetDlgItemText(hwndDlg, IDC_DESTPATH, global_config->ReadString(L"extractpath", m_def_extract_path));
  253. }
  254. }
  255. break;
  256. case IDC_BUTTON2:
  257. wchar_t titleStr[64] = {0};
  258. MessageBox(hwndDlg, WASABI_API_LNGSTRINGW(IDS_COPIED_FILE_FORMAT_INFO),
  259. WASABI_API_LNGSTRINGW_BUF(IDS_COPIED_FILE_FORMAT_HELP,titleStr,64),
  260. MB_OK);
  261. break;
  262. }
  263. break;
  264. }
  265. return 0;
  266. }
  267. INT_PTR CALLBACK config_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam) {
  268. switch(uMsg)
  269. {
  270. case WM_INITDIALOG:
  271. {
  272. config = global_config;
  273. DeviceView * dev = NULL;
  274. for(int i=0; i<devices.GetSize(); i++)
  275. {
  276. dev = (DeviceView *)devices.Get(i);
  277. if(&dev->devPrefsPage == (prefsDlgRecW *)lParam) { configDevice = dev; config = dev->config; break; }
  278. }
  279. if(config == global_config)
  280. {
  281. EndDialog(hwndDlg,0);
  282. return 0;
  283. }
  284. // set the prefs page titles at this stage so that we can have localised versions
  285. int title_ids[] = {IDS_PREFS_SYNC,IDS_PODCAST_SYNC,IDS_PREFS_AUTOFILL,IDS_PREFS_TRANSCODING,IDS_PREFS_VIEW};
  286. for(int i=0; i<sizeof(title_ids)/sizeof(title_ids[0]); i++)
  287. WASABI_API_LNGSTRINGW_BUF(title_ids[i],tabs[i].title,(sizeof(tabs[i].title)/sizeof(wchar_t)));
  288. // set the last item's title to zero otherwise it can cause a dialog to appear incorrectly
  289. tabs[sizeof(tabs)/sizeof(tabs[0])-1].title[0] = 0;
  290. m_hwndTab = GetDlgItem(hwndDlg,IDC_TAB1);
  291. TCITEM tie;
  292. tie.mask = TCIF_TEXT;
  293. int num = 0;
  294. for(int i=0; i<sizeof(tabs)/sizeof(pref_tab); i++)
  295. {
  296. if (dev)
  297. {
  298. if(tabs[i].title[0] == 0)
  299. {
  300. dev->dev->extraActions(DEVICE_GET_PREFS_DIALOG,(intptr_t)&tabs[i],num++,0);
  301. }
  302. // check if we need to show the Transcoding page or not
  303. if (i == TRANS_PREF_IDX && dev->dev->extraActions(DEVICE_VETO_TRANSCODING,0,0,0))
  304. {
  305. tabs[i].title[0] = 0;
  306. }
  307. else
  308. {
  309. // check if a cloud device and drop sync, podcast sync and autofill as appropriate
  310. if (configDevice->isCloudDevice && (i == SYNC_PREF_IDX || i == PODSYNC_PREF_IDX || i == AUTOFILL_PREF_IDX))
  311. {
  312. tabs[i].title[0] = 0;
  313. }
  314. }
  315. }
  316. if(tabs[i].title[0] != 0)
  317. {
  318. tie.pszText=tabs[i].title;
  319. TabCtrl_InsertItem(m_hwndTab,i,&tie);
  320. }
  321. }
  322. TabCtrl_SetCurSel(m_hwndTab,g_prefs_openpage);
  323. OnSelChanged(hwndDlg);
  324. }
  325. break;
  326. case WM_NOTIFY:
  327. {
  328. LPNMHDR lpn = (LPNMHDR) lParam;
  329. if(lpn) if(lpn->code==TCN_SELCHANGE) OnSelChanged(hwndDlg);
  330. }
  331. break;
  332. case WM_DESTROY:
  333. tabs[4].title[0]=0;
  334. configDevice = NULL;
  335. break;
  336. }
  337. return 0;
  338. }
  339. static INT_PTR CALLBACK config_dlgproc_sync(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam) {
  340. static W_ListView m_list;
  341. static int nonotif;
  342. switch(uMsg)
  343. {
  344. case WM_INITDIALOG:
  345. {
  346. nonotif=1;
  347. if(lParam) config_tab_init(hwndDlg,((prefsParam*)lParam)->parent);
  348. if(config->ReadInt(L"syncOnConnect",configDevice->SyncConnectionDefault)==1) CheckDlgButton(hwndDlg,IDC_SYNCONCONNECT,BST_CHECKED);
  349. else EnableWindow(GetDlgItem(hwndDlg,IDC_SYNCONCONNECT_TIME),FALSE);
  350. SetDlgItemText(hwndDlg,IDC_SYNCONCONNECT_TIME,config->ReadString(L"syncOnConnect_hours",L"12"));
  351. SetDlgItemText(hwndDlg,IDC_SYNC_QUERY_STRING,config->ReadString(L"SyncQuery",L"type=0"));
  352. if(config->ReadInt(L"plsyncwhitelist",1)) CheckDlgButton(hwndDlg,IDC_PL_WHITELIST,BST_CHECKED);
  353. else CheckDlgButton(hwndDlg,IDC_PL_BLACKLIST,BST_CHECKED);
  354. if(config->ReadInt(L"syncAllLibrary",1)) CheckDlgButton(hwndDlg,IDC_LIBRARYSYNC,BST_CHECKED);
  355. m_list.setwnd(GetDlgItem(hwndDlg,IDC_PL_LIST));
  356. ListView_SetExtendedListViewStyle(m_list.getwnd(), LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP);
  357. m_list.AddCol(L"",353);
  358. m_list.SetColumnWidth(0, 200);
  359. mlPlaylistInfo playlist = {0};
  360. playlist.size = sizeof(mlPlaylistInfo);
  361. int playlistsnum = SendMessage(plugin.hwndLibraryParent,WM_ML_IPC,0,ML_IPC_PLAYLIST_COUNT);
  362. for(int i=0; i<playlistsnum; i++) {
  363. playlist.playlistNum = i;
  364. SendMessage(plugin.hwndLibraryParent,WM_ML_IPC,(WPARAM)&playlist,ML_IPC_PLAYLIST_INFO);
  365. m_list.InsertItem(i,playlist.playlistName,0);
  366. }
  367. ListView_SetColumnWidth(m_list.getwnd(),0,LVSCW_AUTOSIZE);
  368. for(int i=0; i<playlistsnum; i++) {
  369. playlist.playlistNum = i;
  370. SendMessage(plugin.hwndLibraryParent,WM_ML_IPC,(WPARAM)&playlist,ML_IPC_PLAYLIST_INFO);
  371. wchar_t buf[150] = {0};
  372. StringCchPrintf(buf,150,L"sync-%s",playlist.playlistName);
  373. BOOL state = config->ReadInt(buf,0)?TRUE:FALSE;
  374. ListView_SetCheckState(m_list.getwnd(),i,state);
  375. }
  376. nonotif=0;
  377. if (NULL != WASABI_API_APP)
  378. WASABI_API_APP->DirectMouseWheel_EnableConvertToMouseWheel(m_list.getwnd(), TRUE);
  379. }
  380. break;
  381. case WM_DESTROY:
  382. if (NULL != WASABI_API_APP)
  383. {
  384. HWND listWindow;
  385. listWindow = GetDlgItem(hwndDlg,IDC_PL_LIST);
  386. if (NULL != listWindow)
  387. WASABI_API_APP->DirectMouseWheel_EnableConvertToMouseWheel(listWindow, FALSE);
  388. }
  389. break;
  390. case WM_NOTIFY:
  391. {
  392. LPNMHDR l=(LPNMHDR)lParam;
  393. if (l->idFrom==IDC_PL_LIST && l->code == LVN_ITEMCHANGED && !nonotif) {
  394. LPNMLISTVIEW lv=(LPNMLISTVIEW)lParam;
  395. if(lv->iItem == -1) break;
  396. wchar_t buf[150] = {0}, buf1[125] = {0};
  397. m_list.GetText(lv->iItem,0,buf1,125);
  398. StringCchPrintf(buf,150,L"sync-%s",buf1);
  399. BOOL state = ListView_GetCheckState(m_list.getwnd(),lv->iItem);
  400. config->WriteInt(buf,state?1:0);
  401. }
  402. }
  403. break;
  404. case WM_COMMAND:
  405. switch(LOWORD(wParam)) {
  406. case IDC_SYNCONCONNECT:
  407. config->WriteInt(L"syncOnConnect",IsDlgButtonChecked(hwndDlg,IDC_SYNCONCONNECT)?1:0);
  408. EnableWindow(GetDlgItem(hwndDlg,IDC_SYNCONCONNECT_TIME),IsDlgButtonChecked(hwndDlg,IDC_SYNCONCONNECT));
  409. break;
  410. case IDC_SYNCONCONNECT_TIME:
  411. if(HIWORD(wParam) == EN_CHANGE) {
  412. wchar_t buf[100]=L"";
  413. GetDlgItemText(hwndDlg,IDC_SYNCONCONNECT_TIME,buf,100);
  414. config->WriteInt(L"syncOnConnect_hours",_wtoi(buf));
  415. }
  416. break;
  417. case IDC_PL_WHITELIST:
  418. case IDC_PL_BLACKLIST:
  419. config->WriteInt(L"plsyncwhitelist",IsDlgButtonChecked(hwndDlg,IDC_PL_WHITELIST)?1:0);
  420. break;
  421. case IDC_LIBRARYSYNC:
  422. config->WriteInt(L"syncAllLibrary",IsDlgButtonChecked(hwndDlg,IDC_LIBRARYSYNC)?1:0);
  423. break;
  424. case IDC_SYNC_QUERY_STRING:
  425. if (HIWORD(wParam) == EN_KILLFOCUS) {
  426. wchar_t buf[1024] = {0};
  427. GetDlgItemText(hwndDlg,IDC_SYNC_QUERY_STRING,buf,1024);
  428. config->WriteString(L"SyncQuery",buf);
  429. }
  430. break;
  431. case IDC_SYNC_QUERY_EDIT:
  432. {
  433. char temp[1024] = {0};
  434. GetDlgItemTextA(hwndDlg, IDC_SYNC_QUERY_STRING, temp, sizeof(temp) - 1);
  435. ml_editview meq = {hwndDlg,temp,"Sync Query",-1};
  436. meq.name = WASABI_API_LNGSTRING(IDS_SYNC_QUERY);
  437. if(!(int)SendMessage(plugin.hwndLibraryParent,WM_ML_IPC,(LPARAM)&meq,ML_IPC_EDITVIEW)) return 0;
  438. SetDlgItemTextA(hwndDlg, IDC_SYNC_QUERY_STRING, meq.query);
  439. config->WriteString(L"SyncQuery",AutoWide(meq.query));
  440. }
  441. break;
  442. }
  443. break;
  444. }
  445. return 0;
  446. }
  447. static INT_PTR CALLBACK config_dlgproc_cloud_sync(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam) {
  448. static W_ListView m_list;
  449. static int nonotif;
  450. switch(uMsg)
  451. {
  452. case WM_INITDIALOG:
  453. {
  454. nonotif=1;
  455. if(lParam) config_tab_init(hwndDlg,((prefsParam*)lParam)->parent);
  456. if(config->ReadInt(L"syncOnConnect",configDevice->SyncConnectionDefault)==1) CheckDlgButton(hwndDlg,IDC_SYNCONCONNECT,BST_CHECKED);
  457. else EnableWindow(GetDlgItem(hwndDlg,IDC_SYNCONCONNECT_TIME),FALSE);
  458. SetDlgItemText(hwndDlg,IDC_SYNCONCONNECT_TIME,config->ReadString(L"syncOnConnect_hours",L"12"));
  459. SetDlgItemText(hwndDlg,IDC_SYNC_QUERY_STRING,config->ReadString(L"SyncQuery",L"type=0"));
  460. if(config->ReadInt(L"plsyncwhitelist",1)) CheckDlgButton(hwndDlg,IDC_PL_WHITELIST,BST_CHECKED);
  461. else CheckDlgButton(hwndDlg,IDC_PL_BLACKLIST,BST_CHECKED);
  462. if(config->ReadInt(L"syncAllLibrary",1)) CheckDlgButton(hwndDlg,IDC_LIBRARYSYNC,BST_CHECKED);
  463. m_list.setwnd(GetDlgItem(hwndDlg,IDC_PL_LIST));
  464. ListView_SetExtendedListViewStyle(m_list.getwnd(), LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP);
  465. m_list.AddCol(L"",353);
  466. mlPlaylistInfo playlist = {0};
  467. playlist.size = sizeof(mlPlaylistInfo);
  468. int playlistsnum = SendMessage(plugin.hwndLibraryParent,WM_ML_IPC,0,ML_IPC_PLAYLIST_COUNT);
  469. for(int i=0; i<playlistsnum; i++) {
  470. playlist.playlistNum = i;
  471. SendMessage(plugin.hwndLibraryParent,WM_ML_IPC,(WPARAM)&playlist,ML_IPC_PLAYLIST_INFO);
  472. m_list.InsertItem(i,playlist.playlistName,0);
  473. }
  474. ListView_SetColumnWidth(m_list.getwnd(),0,LVSCW_AUTOSIZE);
  475. for(int i=0; i<playlistsnum; i++) {
  476. playlist.playlistNum = i;
  477. SendMessage(plugin.hwndLibraryParent,WM_ML_IPC,(WPARAM)&playlist,ML_IPC_PLAYLIST_INFO);
  478. wchar_t buf[150] = {0};
  479. StringCchPrintf(buf,150,L"sync-%s",playlist.playlistName);
  480. BOOL state = config->ReadInt(buf,0)?TRUE:FALSE;
  481. ListView_SetCheckState(m_list.getwnd(),i,state);
  482. }
  483. nonotif=0;
  484. if (NULL != WASABI_API_APP)
  485. WASABI_API_APP->DirectMouseWheel_EnableConvertToMouseWheel(m_list.getwnd(), TRUE);
  486. }
  487. break;
  488. case WM_DESTROY:
  489. if (NULL != WASABI_API_APP)
  490. {
  491. HWND listWindow;
  492. listWindow = GetDlgItem(hwndDlg,IDC_PL_LIST);
  493. if (NULL != listWindow)
  494. WASABI_API_APP->DirectMouseWheel_EnableConvertToMouseWheel(listWindow, FALSE);
  495. }
  496. break;
  497. case WM_NOTIFY:
  498. {
  499. LPNMHDR l=(LPNMHDR)lParam;
  500. if (l->idFrom==IDC_PL_LIST && l->code == LVN_ITEMCHANGED && !nonotif) {
  501. LPNMLISTVIEW lv=(LPNMLISTVIEW)lParam;
  502. if(lv->iItem == -1) break;
  503. wchar_t buf[150] = {0}, buf1[125] = {0};
  504. m_list.GetText(lv->iItem,0,buf1,125);
  505. StringCchPrintf(buf,150,L"sync-%s",buf1);
  506. BOOL state = ListView_GetCheckState(m_list.getwnd(),lv->iItem);
  507. config->WriteInt(buf,state?1:0);
  508. }
  509. }
  510. break;
  511. case WM_COMMAND:
  512. switch(LOWORD(wParam)) {
  513. case IDC_SYNCONCONNECT:
  514. config->WriteInt(L"syncOnConnect",IsDlgButtonChecked(hwndDlg,IDC_SYNCONCONNECT)?1:0);
  515. EnableWindow(GetDlgItem(hwndDlg,IDC_SYNCONCONNECT_TIME),IsDlgButtonChecked(hwndDlg,IDC_SYNCONCONNECT));
  516. break;
  517. case IDC_SYNCONCONNECT_TIME:
  518. if(HIWORD(wParam) == EN_CHANGE) {
  519. wchar_t buf[100]=L"";
  520. GetDlgItemText(hwndDlg,IDC_SYNCONCONNECT_TIME,buf,100);
  521. config->WriteInt(L"syncOnConnect_hours",_wtoi(buf));
  522. }
  523. break;
  524. case IDC_PL_WHITELIST:
  525. case IDC_PL_BLACKLIST:
  526. config->WriteInt(L"plsyncwhitelist",IsDlgButtonChecked(hwndDlg,IDC_PL_WHITELIST)?1:0);
  527. break;
  528. case IDC_LIBRARYSYNC:
  529. config->WriteInt(L"syncAllLibrary",IsDlgButtonChecked(hwndDlg,IDC_LIBRARYSYNC)?1:0);
  530. break;
  531. case IDC_SYNC_QUERY_STRING:
  532. if (HIWORD(wParam) == EN_KILLFOCUS) {
  533. wchar_t buf[1024] = {0};
  534. GetDlgItemText(hwndDlg,IDC_SYNC_QUERY_STRING,buf,1024);
  535. config->WriteString(L"SyncQuery",buf);
  536. }
  537. break;
  538. case IDC_SYNC_QUERY_EDIT:
  539. {
  540. char temp[1024] = {0};
  541. GetDlgItemTextA(hwndDlg, IDC_SYNC_QUERY_STRING, temp, sizeof(temp) - 1);
  542. ml_editview meq = {hwndDlg,temp,"Sync Query",-1};
  543. meq.name = WASABI_API_LNGSTRING(IDS_SYNC_QUERY);
  544. if(!(int)SendMessage(plugin.hwndLibraryParent,WM_ML_IPC,(LPARAM)&meq,ML_IPC_EDITVIEW)) return 0;
  545. SetDlgItemTextA(hwndDlg, IDC_SYNC_QUERY_STRING, meq.query);
  546. config->WriteString(L"SyncQuery",AutoWide(meq.query));
  547. }
  548. break;
  549. }
  550. break;
  551. }
  552. return 0;
  553. }
  554. static INT_PTR CALLBACK config_dlgproc_podcast_sync(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam) {
  555. static W_ListView m_list2;
  556. static int nonotif;
  557. switch(uMsg)
  558. {
  559. case WM_INITDIALOG:
  560. {
  561. nonotif=1;
  562. if(lParam) config_tab_init(hwndDlg,((prefsParam*)lParam)->parent);
  563. m_list2.setwnd(GetDlgItem(hwndDlg,IDC_PC_LIST));
  564. ListView_SetExtendedListViewStyle(m_list2.getwnd(), LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP);
  565. m_list2.AddCol(L"",215);
  566. if (configDevice->dev->extraActions(DEVICE_SUPPORTS_PODCASTS, 0,0, 0) == 0) {
  567. int podcastsnum = AGAVE_API_PODCASTS?AGAVE_API_PODCASTS->GetNumPodcasts():0;
  568. for(int i=0; i<podcastsnum; i++) {
  569. ifc_podcast *podcast = AGAVE_API_PODCASTS->EnumPodcast(i);
  570. if (podcast) {
  571. wchar_t podcast_name[256] = {0};
  572. if (podcast->GetTitle(podcast_name, 256) == 0 && podcast_name[0])
  573. {
  574. m_list2.InsertItem(i,podcast_name,0);
  575. }
  576. }
  577. }
  578. ListView_SetColumnWidth(m_list2.getwnd(),0,LVSCW_AUTOSIZE);
  579. for(int i=0; i<podcastsnum; i++) {
  580. ifc_podcast *podcast = AGAVE_API_PODCASTS->EnumPodcast(i);
  581. if (podcast) {
  582. wchar_t podcast_name[256] = {0};
  583. if (podcast->GetTitle(podcast_name, 256) == 0 && podcast_name[0]) {
  584. wchar_t buf[300] = {0};
  585. StringCchPrintf(buf,300,L"podcast-sync-%s",podcast_name);
  586. BOOL state = config->ReadInt(buf,0)?TRUE:FALSE;
  587. ListView_SetCheckState(m_list2.getwnd(),i,state);
  588. }
  589. }
  590. }
  591. int podcast_eps = config->ReadInt(L"podcast-sync_episodes",0);
  592. if(podcast_eps == 0) {
  593. podcast_eps=3;
  594. } else
  595. CheckDlgButton(hwndDlg,IDC_CHECK_PC,BST_CHECKED);
  596. for(int i=0; i<6; i++) {
  597. int a,d;
  598. if(i==0) {
  599. a = SendDlgItemMessage(hwndDlg,IDC_COMBO_PC_NUM,CB_ADDSTRING,0,
  600. (LPARAM)WASABI_API_LNGSTRINGW(IDS_ALL));
  601. d = -1;
  602. } else {
  603. wchar_t buf[10] = {0};
  604. StringCchPrintf(buf,100,L"%d",i);
  605. a = SendDlgItemMessage(hwndDlg,IDC_COMBO_PC_NUM,CB_ADDSTRING,0,(LPARAM)buf);
  606. d = i;
  607. }
  608. SendDlgItemMessage(hwndDlg,IDC_COMBO_PC_NUM,CB_SETITEMDATA,a,(LPARAM)d);
  609. if(d == podcast_eps) SendDlgItemMessage(hwndDlg, IDC_COMBO_PC_NUM, CB_SETCURSEL, (WPARAM)a, 0);
  610. }
  611. if(config->ReadInt(L"podcast-sync_all",1)) CheckDlgButton(hwndDlg,IDC_PC_ALL,BST_CHECKED);
  612. else CheckDlgButton(hwndDlg,IDC_PC_SEL,BST_CHECKED);
  613. }
  614. else {
  615. EnableWindow(GetDlgItem(hwndDlg, IDC_CHECK_PC), FALSE);
  616. }
  617. SendMessage(hwndDlg,WM_COMMAND,IDC_CHECK_PC,0xdeadbeef);
  618. nonotif=0;
  619. if (NULL != WASABI_API_APP)
  620. WASABI_API_APP->DirectMouseWheel_EnableConvertToMouseWheel(m_list2.getwnd(), TRUE);
  621. }
  622. break;
  623. case WM_DESTROY:
  624. if (NULL != WASABI_API_APP)
  625. {
  626. HWND listWindow;
  627. listWindow = GetDlgItem(hwndDlg,IDC_PL_LIST);
  628. if (NULL != listWindow)
  629. WASABI_API_APP->DirectMouseWheel_EnableConvertToMouseWheel(listWindow, FALSE);
  630. }
  631. break;
  632. case WM_NOTIFY:
  633. {
  634. LPNMHDR l=(LPNMHDR)lParam;
  635. if (l->idFrom==IDC_PC_LIST && l->code == LVN_ITEMCHANGED && !nonotif) {
  636. LPNMLISTVIEW lv=(LPNMLISTVIEW)lParam;
  637. if(lv->iItem == -1) break;
  638. wchar_t buf[150] = {0}, buf1[125] = {0};
  639. m_list2.GetText(lv->iItem,0,buf1,125);
  640. StringCchPrintf(buf,150,L"podcast-sync-%s",buf1);
  641. BOOL state = ListView_GetCheckState(m_list2.getwnd(),lv->iItem);
  642. config->WriteInt(buf,state?1:0);
  643. }
  644. }
  645. break;
  646. case WM_COMMAND:
  647. switch(LOWORD(wParam)) {
  648. case IDC_CHECK_PC:
  649. {
  650. BOOL e = IsDlgButtonChecked(hwndDlg,IDC_CHECK_PC);
  651. EnableWindow(GetDlgItem(hwndDlg,IDC_COMBO_PC_NUM),e);
  652. EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC_PODTXT),e);
  653. EnableWindow(GetDlgItem(hwndDlg,IDC_PC_ALL),e);
  654. EnableWindow(GetDlgItem(hwndDlg,IDC_PC_SEL),e);
  655. EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC_PODTIP),e);
  656. EnableWindow(GetDlgItem(hwndDlg,IDC_PC_LIST),e && IsDlgButtonChecked(hwndDlg,IDC_PC_SEL));
  657. if(lParam != 0xdeadbeef) {
  658. if(e) {
  659. int b = SendDlgItemMessage(hwndDlg, IDC_COMBO_PC_NUM, CB_GETCURSEL, 0, 0);
  660. if(b>=0) {
  661. int x = SendDlgItemMessage(hwndDlg, IDC_COMBO_PC_NUM, CB_GETITEMDATA, b, 0);
  662. config->WriteInt(L"podcast-sync_episodes", x);
  663. }
  664. }
  665. else config->WriteInt(L"podcast-sync_episodes",0);
  666. }
  667. }
  668. break;
  669. case IDC_PC_SEL:
  670. case IDC_PC_ALL:
  671. {
  672. BOOL e = IsDlgButtonChecked(hwndDlg,IDC_PC_SEL);
  673. EnableWindow(GetDlgItem(hwndDlg,IDC_PC_LIST),e);
  674. config->WriteInt(L"podcast-sync_all",!e);
  675. }
  676. break;
  677. case IDC_COMBO_PC_NUM:
  678. if(HIWORD(wParam) == CBN_SELCHANGE) {
  679. int b = SendDlgItemMessage(hwndDlg, IDC_COMBO_PC_NUM, CB_GETCURSEL, 0, 0);
  680. if (b >= 0) {
  681. int x = SendDlgItemMessage(hwndDlg, IDC_COMBO_PC_NUM, CB_GETITEMDATA, b, 0);
  682. config->WriteInt(L"podcast-sync_episodes", x);
  683. }
  684. }
  685. break;
  686. }
  687. break;
  688. }
  689. return 0;
  690. }
  691. static INT_PTR CALLBACK config_dlgproc_autofill(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam) {
  692. switch(uMsg)
  693. {
  694. case WM_INITDIALOG:
  695. if(lParam) config_tab_init(hwndDlg,((prefsParam*)lParam)->parent);
  696. if(config->ReadInt(L"syncOnConnect",configDevice->SyncConnectionDefault)==2) CheckDlgButton(hwndDlg,IDC_SYNCONCONNECT,BST_CHECKED);
  697. else EnableWindow(GetDlgItem(hwndDlg,IDC_SYNCONCONNECT_TIME),FALSE);
  698. SetDlgItemText(hwndDlg,IDC_SYNCONCONNECT_TIME,config->ReadString(L"syncOnConnect_hours",L"12"));
  699. if(lstrlen(config->ReadString(L"AutoFillRatings",L""))!=0) CheckDlgButton(hwndDlg,IDC_BOOSTRATINGS,BST_CHECKED);
  700. if(config->ReadInt(L"AlbumAutoFill",0)) CheckDlgButton(hwndDlg,IDC_AUTOFILLALBUMS,BST_CHECKED);
  701. SetDlgItemText(hwndDlg,IDC_AUTOFILL_QUERY_STRING,config->ReadString(L"AutoFillQuery",L"length > 30"));
  702. SendMessage(GetDlgItem(hwndDlg,IDC_SPACESLIDER),TBM_SETRANGEMAX, TRUE, 100);
  703. SendMessage(GetDlgItem(hwndDlg,IDC_SPACESLIDER),TBM_SETRANGEMIN, TRUE, 0);
  704. SendMessage(GetDlgItem(hwndDlg,IDC_SPACESLIDER),TBM_SETPOS, TRUE, config->ReadInt(L"FillPercent",90));
  705. break;
  706. case WM_NOTIFY:
  707. switch (LOWORD(wParam))
  708. {
  709. case IDC_SPACESLIDER:
  710. {
  711. int spaceToAutofill = SendMessage(GetDlgItem(hwndDlg,IDC_SPACESLIDER),TBM_GETPOS,0,0);
  712. wchar_t tmp[100]=L"";
  713. StringCchPrintf(tmp,100,WASABI_API_LNGSTRINGW(IDS_AIM_TO_AUTOFILL_DEVICE),spaceToAutofill);
  714. SetDlgItemText(hwndDlg, IDC_FILLCAPTION, tmp);
  715. config->WriteInt(L"FillPercent",spaceToAutofill);
  716. }
  717. break;
  718. }
  719. break;
  720. case WM_COMMAND:
  721. switch(LOWORD(wParam))
  722. {
  723. case IDC_SYNCONCONNECT:
  724. config->WriteInt(L"syncOnConnect",IsDlgButtonChecked(hwndDlg,IDC_SYNCONCONNECT)?2:0);
  725. EnableWindow(GetDlgItem(hwndDlg,IDC_SYNCONCONNECT_TIME),IsDlgButtonChecked(hwndDlg,IDC_SYNCONCONNECT));
  726. break;
  727. case IDC_SYNCONCONNECT_TIME:
  728. if(HIWORD(wParam) == EN_CHANGE)
  729. {
  730. wchar_t buf[100]=L"";
  731. GetDlgItemText(hwndDlg,IDC_SYNCONCONNECT_TIME,buf,100);
  732. config->WriteInt(L"syncOnConnect_hours",_wtoi(buf));
  733. }
  734. break;
  735. case IDC_AUTOFILL_QUERY_STRING:
  736. if (HIWORD(wParam) == EN_KILLFOCUS)
  737. {
  738. wchar_t buf[1024] = {0};
  739. GetDlgItemText(hwndDlg,IDC_AUTOFILL_QUERY_STRING,buf,1024);
  740. config->WriteString(L"AutoFillQuery",buf);
  741. }
  742. break;
  743. case IDC_AUTOFILL_QUERY_EDIT:
  744. {
  745. char temp[1024] = {0};
  746. GetDlgItemTextA(hwndDlg, IDC_AUTOFILL_QUERY_STRING, temp, sizeof(temp) - 1);
  747. ml_editview meq = {hwndDlg,temp,0,-1};
  748. meq.name = WASABI_API_LNGSTRING(IDS_AUTOFILL_QUERY);
  749. if(!(int)SendMessage(plugin.hwndLibraryParent,WM_ML_IPC,(LPARAM)&meq,ML_IPC_EDITVIEW)) return 0;
  750. SetDlgItemTextA(hwndDlg, IDC_AUTOFILL_QUERY_STRING, meq.query);
  751. config->WriteString(L"AutoFillQuery",AutoWide(meq.query));
  752. }
  753. break;
  754. case IDC_BOOSTRATINGS:
  755. if(IsDlgButtonChecked(hwndDlg,IDC_BOOSTRATINGS)) config->WriteString(L"AutoFillRatings",L"20:18:15:13:11:10");
  756. else config->WriteString(L"AutoFillRatings",L"");
  757. break;
  758. case IDC_AUTOFILLALBUMS:
  759. config->WriteInt(L"AlbumAutoFill",IsDlgButtonChecked(hwndDlg,IDC_AUTOFILLALBUMS)?1:0);
  760. break;
  761. }
  762. break;
  763. }
  764. const int controls[] =
  765. {
  766. IDC_SPACESLIDER,
  767. };
  768. if (FALSE != WASABI_API_APP->DirectMouseWheel_ProcessDialogMessage(hwndDlg, uMsg, wParam, lParam, controls, ARRAYSIZE(controls)))
  769. return TRUE;
  770. return 0;
  771. }
  772. static INT_PTR CALLBACK config_dlgproc_transcode(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam) {
  773. switch(uMsg)
  774. {
  775. case WM_INITDIALOG:
  776. {
  777. Device *dev = 0;
  778. if(lParam)
  779. {
  780. config_tab_init(hwndDlg,((prefsParam*)lParam)->parent);
  781. dev = ((prefsParam*)lParam)->dev;
  782. }
  783. lParam = (LPARAM)TranscoderImp::ConfigureTranscoder(L"ml_pmp",plugin.hwndWinampParent,config, dev);
  784. }
  785. break;
  786. }
  787. return TranscoderImp::transcodeconfig_dlgproc(hwndDlg,uMsg,wParam,lParam);
  788. }
  789. static INT_PTR CALLBACK config_dlgproc_mediaview(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam) {
  790. switch(uMsg) {
  791. case WM_INITDIALOG:
  792. {
  793. if(lParam) config_tab_init(hwndDlg,((prefsParam*)lParam)->parent);
  794. int fieldsBits = (int)configDevice->dev->extraActions(DEVICE_SUPPORTED_METADATA,0,0,0);
  795. if(!fieldsBits) fieldsBits=-1;
  796. // used to ensure that the filters will work irrespective of language in use
  797. wchar_t * filters[] = {
  798. (fieldsBits&SUPPORTS_ARTIST)?L"Artist":0,
  799. (fieldsBits&SUPPORTS_ALBUM)?L"Album":0,
  800. (fieldsBits&SUPPORTS_GENRE)?L"Genre":0,
  801. (fieldsBits&SUPPORTS_YEAR)?L"Year":0,
  802. (fieldsBits&SUPPORTS_ALBUMARTIST)?L"Album Artist":0,
  803. (fieldsBits&SUPPORTS_PUBLISHER)?L"Publisher":0,
  804. (fieldsBits&SUPPORTS_COMPOSER)?L"Composer":0,
  805. (fieldsBits&SUPPORTS_ARTIST)?L"Artist Index":0,
  806. (fieldsBits&SUPPORTS_ALBUMARTIST)?L"Album Artist Index":0,
  807. (fieldsBits&SUPPORTS_ALBUMART)?L"Album Art":0,
  808. (fieldsBits&SUPPORTS_MIMETYPE)?L"Mime":0,
  809. (fieldsBits&SUPPORTS_DATEADDED)?L"Date Added":0,
  810. };
  811. // used for displayed items - localised crazyness, heh
  812. int filters_idx[] = {
  813. (fieldsBits&SUPPORTS_ARTIST)?IDS_ARTIST:0,
  814. (fieldsBits&SUPPORTS_ALBUM)?IDS_ALBUM:0,
  815. (fieldsBits&SUPPORTS_GENRE)?IDS_GENRE:0,
  816. (fieldsBits&SUPPORTS_YEAR)?IDS_YEAR:0,
  817. (fieldsBits&SUPPORTS_ALBUMARTIST)?IDS_ALBUM_ARTIST:0,
  818. (fieldsBits&SUPPORTS_PUBLISHER)?IDS_PUBLISHER:0,
  819. (fieldsBits&SUPPORTS_COMPOSER)?IDS_COMPOSER:0,
  820. (fieldsBits&SUPPORTS_ARTIST)?IDS_ARTIST_INDEX:0,
  821. (fieldsBits&SUPPORTS_ALBUMARTIST)?IDS_ALBUM_ARTIST_INDEX:0,
  822. (fieldsBits&SUPPORTS_ALBUMART)?IDS_ALBUM_ART:0,
  823. (fieldsBits&SUPPORTS_MIMETYPE)?IDS_MIME_TYPE:0,
  824. (fieldsBits&SUPPORTS_DATEADDED)?IDS_DATE_ADDED:0,
  825. };
  826. int numFilters = config->ReadInt(L"media_numfilters",2);
  827. CheckRadioButton(hwndDlg, IDC_RADIO_FILTERS1, IDC_RADIO_FILTERS3, (IDC_RADIO_FILTERS1 + numFilters - 1));
  828. CheckDlgButton(hwndDlg, IDC_REMEMBER_SEARCH, config->ReadInt(L"savefilter", 1));
  829. for(int i=0; i<3; i++) {
  830. int id = (i==0)?IDC_COMBO_FILTER1:((i==1)?IDC_COMBO_FILTER2:IDC_COMBO_FILTER3);
  831. for(int j=0; j<(sizeof(filters)/sizeof(wchar_t*)); j++) {
  832. if(filters[j]) {
  833. int a = SendDlgItemMessage(hwndDlg,id,CB_ADDSTRING,0,
  834. (LPARAM)WASABI_API_LNGSTRINGW(filters_idx[j]));
  835. SendDlgItemMessage(hwndDlg,id,CB_SETITEMDATA,a,(LPARAM)filters[j]);
  836. }
  837. }
  838. wchar_t name[20] = {0};
  839. StringCchPrintf(name,20,L"media_filter%d",i);
  840. extern wchar_t *GetDefFilter(int i,int n);
  841. SendDlgItemMessage(hwndDlg,id,CB_SETCURSEL,0,0);
  842. wchar_t* filterStr = config->ReadString(name,GetDefFilter(i,numFilters));
  843. for(int l = 0; l < (sizeof(filters)/sizeof(wchar_t*)); l++) {
  844. wchar_t* x = (wchar_t*)SendDlgItemMessage(hwndDlg,id,CB_GETITEMDATA,l,0);
  845. if(x && x != (wchar_t*)-1 && !_wcsicmp(filterStr,x)) {
  846. SendDlgItemMessage(hwndDlg,id,CB_SETCURSEL,(WPARAM)l,0);
  847. break;
  848. }
  849. }
  850. }
  851. if(configDevice->videoView) CheckDlgButton(hwndDlg,IDC_CHECK_VIDEOVIEW,TRUE);
  852. }
  853. SendMessage(hwndDlg,WM_USER,0,0);
  854. break;
  855. case WM_USER:
  856. {
  857. BOOL full_enable = (IsDlgButtonChecked(hwndDlg,IDC_RADIO_FILTERS1) != BST_CHECKED);
  858. EnableWindow(GetDlgItem(hwndDlg, IDC_COMBO_FILTER1), full_enable);
  859. EnableWindow(GetDlgItem(hwndDlg, IDC_STATIC_FILTER2), full_enable);
  860. EnableWindow(GetDlgItem(hwndDlg, IDC_COMBO_FILTER2), full_enable);
  861. BOOL enable = (IsDlgButtonChecked(hwndDlg, IDC_RADIO_FILTERS3) == BST_CHECKED) && full_enable;
  862. EnableWindow(GetDlgItem(hwndDlg, IDC_STATIC_FILTER3), enable);
  863. EnableWindow(GetDlgItem(hwndDlg, IDC_COMBO_FILTER3), enable);
  864. }
  865. break;
  866. case WM_COMMAND:
  867. switch(LOWORD(wParam)) {
  868. case IDC_RADIO_FILTERS3:
  869. case IDC_RADIO_FILTERS2:
  870. case IDC_RADIO_FILTERS1:
  871. SendMessage(hwndDlg,WM_USER,0,0);
  872. break;
  873. case IDC_CHECK_VIDEOVIEW:
  874. configDevice->SetVideoView(IsDlgButtonChecked(hwndDlg,IDC_CHECK_VIDEOVIEW));
  875. break;
  876. case IDC_REMEMBER_SEARCH:
  877. config->WriteInt(L"savefilter", IsDlgButtonChecked(hwndDlg,IDC_REMEMBER_SEARCH));
  878. config->WriteString(L"savedfilter", L"");
  879. config->WriteString(L"savedrefinefilter", L"");
  880. break;
  881. }
  882. break;
  883. case WM_DESTROY:
  884. {
  885. int update_needed = false;
  886. int numFilters = config->ReadInt(L"media_numfilters",2);
  887. int new_numFilters = 1;
  888. if (IsDlgButtonChecked(hwndDlg,IDC_RADIO_FILTERS1)) new_numFilters = 1;
  889. else if (IsDlgButtonChecked(hwndDlg,IDC_RADIO_FILTERS2)) new_numFilters = 2;
  890. else if (IsDlgButtonChecked(hwndDlg,IDC_RADIO_FILTERS3)) new_numFilters = 3;
  891. if (new_numFilters != numFilters) update_needed++;
  892. config->WriteInt(L"media_numfilters",new_numFilters);
  893. for(int i=0; i<3; i++) {
  894. int id = (i==0)?IDC_COMBO_FILTER1:((i==1)?IDC_COMBO_FILTER2:IDC_COMBO_FILTER3);
  895. int sel = SendDlgItemMessage(hwndDlg, id, CB_GETCURSEL, 0, 0);
  896. wchar_t * x = (wchar_t*)SendDlgItemMessage(hwndDlg, id, CB_GETITEMDATA, sel, 0);
  897. wchar_t name[20] = {0};
  898. StringCchPrintf(name,20,L"media_filter%d",i);
  899. extern wchar_t *GetDefFilter(int i,int n);
  900. SendDlgItemMessage(hwndDlg,id,CB_SETCURSEL,0,0);
  901. wchar_t* filterStr = config->ReadString(name,GetDefFilter(i,new_numFilters));
  902. if(x && x != (wchar_t*)-1)
  903. {
  904. config->WriteString(name,x);
  905. update_needed += (wcscmp(filterStr, x));
  906. }
  907. }
  908. // only refresh the view if it is one of ours (is a bit silly
  909. // otherwise) and also not refresh unless there was a change
  910. // with the configDevice check to cope with going elsewhere
  911. if (update_needed && ((configDevice && configDevice == currentViewedDevice) || IsWindow(hwndMediaView))) {
  912. PostMessage(plugin.hwndLibraryParent, WM_USER + 30, 0, 0);
  913. }
  914. }
  915. break;
  916. }
  917. return 0;
  918. }
  919. static INT_PTR CALLBACK config_dlgproc_cloud_mediaview(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam) {
  920. switch(uMsg) {
  921. case WM_INITDIALOG:
  922. {
  923. if(lParam) config_tab_init(hwndDlg,((prefsParam*)lParam)->parent);
  924. int fieldsBits = (int)configDevice->dev->extraActions(DEVICE_SUPPORTED_METADATA,0,0,0);
  925. if(!fieldsBits) fieldsBits=-1;
  926. // used to ensure that the filters will work irrespective of language in use
  927. wchar_t * filters[] = {
  928. (fieldsBits&SUPPORTS_ARTIST)?L"Artist":0,
  929. (fieldsBits&SUPPORTS_ALBUM)?L"Album":0,
  930. (fieldsBits&SUPPORTS_GENRE)?L"Genre":0,
  931. (fieldsBits&SUPPORTS_YEAR)?L"Year":0,
  932. (fieldsBits&SUPPORTS_ALBUMARTIST)?L"Album Artist":0,
  933. (fieldsBits&SUPPORTS_PUBLISHER)?L"Publisher":0,
  934. (fieldsBits&SUPPORTS_COMPOSER)?L"Composer":0,
  935. (fieldsBits&SUPPORTS_ARTIST)?L"Artist Index":0,
  936. (fieldsBits&SUPPORTS_ALBUMARTIST)?L"Album Artist Index":0,
  937. (fieldsBits&SUPPORTS_ALBUMART)?L"Album Art":0,
  938. (fieldsBits&SUPPORTS_MIMETYPE)?L"Mime":0,
  939. (fieldsBits&SUPPORTS_DATEADDED)?L"Date Added":0,
  940. };
  941. // used for displayed items - localised crazyness, heh
  942. int filters_idx[] = {
  943. (fieldsBits&SUPPORTS_ARTIST)?IDS_ARTIST:0,
  944. (fieldsBits&SUPPORTS_ALBUM)?IDS_ALBUM:0,
  945. (fieldsBits&SUPPORTS_GENRE)?IDS_GENRE:0,
  946. (fieldsBits&SUPPORTS_YEAR)?IDS_YEAR:0,
  947. (fieldsBits&SUPPORTS_ALBUMARTIST)?IDS_ALBUM_ARTIST:0,
  948. (fieldsBits&SUPPORTS_PUBLISHER)?IDS_PUBLISHER:0,
  949. (fieldsBits&SUPPORTS_COMPOSER)?IDS_COMPOSER:0,
  950. (fieldsBits&SUPPORTS_ARTIST)?IDS_ARTIST_INDEX:0,
  951. (fieldsBits&SUPPORTS_ALBUMARTIST)?IDS_ALBUM_ARTIST_INDEX:0,
  952. (fieldsBits&SUPPORTS_ALBUMART)?IDS_ALBUM_ART:0,
  953. (fieldsBits&SUPPORTS_MIMETYPE)?IDS_MIME_TYPE:0,
  954. (fieldsBits&SUPPORTS_DATEADDED)?IDS_DATE_ADDED:0,
  955. };
  956. int numFilters = config->ReadInt(L"media_numfilters",2);
  957. CheckRadioButton(hwndDlg, IDC_RADIO_FILTERS1, IDC_RADIO_FILTERS3, (IDC_RADIO_FILTERS1 + numFilters - 1));
  958. CheckDlgButton(hwndDlg, IDC_REMEMBER_SEARCH, config->ReadInt(L"savefilter", 1));
  959. for(int i=0; i<3; i++) {
  960. int id = (i==0)?IDC_COMBO_FILTER1:((i==1)?IDC_COMBO_FILTER2:IDC_COMBO_FILTER3);
  961. for(int j=0; j<(sizeof(filters)/sizeof(wchar_t*)); j++) {
  962. if(filters[j]) {
  963. int a = SendDlgItemMessage(hwndDlg,id,CB_ADDSTRING,0,
  964. (LPARAM)WASABI_API_LNGSTRINGW(filters_idx[j]));
  965. SendDlgItemMessage(hwndDlg,id,CB_SETITEMDATA,a,(LPARAM)filters[j]);
  966. }
  967. }
  968. wchar_t name[20] = {0};
  969. StringCchPrintf(name,20,L"media_filter%d",i);
  970. extern wchar_t *GetDefFilter(int i,int n);
  971. SendDlgItemMessage(hwndDlg,id,CB_SETCURSEL,0,0);
  972. wchar_t* filterStr = config->ReadString(name,GetDefFilter(i,numFilters));
  973. for(int l = 0; l < (sizeof(filters)/sizeof(wchar_t*)); l++) {
  974. wchar_t* x = (wchar_t*)SendDlgItemMessage(hwndDlg,id,CB_GETITEMDATA,l,0);
  975. if(x && x != (wchar_t*)-1 && !_wcsicmp(filterStr,x)) {
  976. SendDlgItemMessage(hwndDlg,id,CB_SETCURSEL,(WPARAM)l,0);
  977. break;
  978. }
  979. }
  980. }
  981. }
  982. SendMessage(hwndDlg,WM_USER,0,0);
  983. break;
  984. case WM_USER:
  985. {
  986. BOOL full_enable = (IsDlgButtonChecked(hwndDlg,IDC_RADIO_FILTERS1) != BST_CHECKED);
  987. EnableWindow(GetDlgItem(hwndDlg, IDC_COMBO_FILTER1), full_enable);
  988. EnableWindow(GetDlgItem(hwndDlg, IDC_STATIC_FILTER2), full_enable);
  989. EnableWindow(GetDlgItem(hwndDlg, IDC_COMBO_FILTER2), full_enable);
  990. BOOL enable = (IsDlgButtonChecked(hwndDlg, IDC_RADIO_FILTERS3) == BST_CHECKED) && full_enable;
  991. EnableWindow(GetDlgItem(hwndDlg, IDC_STATIC_FILTER3), enable);
  992. EnableWindow(GetDlgItem(hwndDlg, IDC_COMBO_FILTER3), enable);
  993. }
  994. break;
  995. case WM_COMMAND:
  996. switch(LOWORD(wParam)) {
  997. case IDC_RADIO_FILTERS3:
  998. case IDC_RADIO_FILTERS2:
  999. case IDC_RADIO_FILTERS1:
  1000. SendMessage(hwndDlg,WM_USER,0,0);
  1001. break;
  1002. case IDC_REMEMBER_SEARCH:
  1003. config->WriteInt(L"savefilter", IsDlgButtonChecked(hwndDlg,IDC_REMEMBER_SEARCH));
  1004. config->WriteString(L"savedfilter", L"");
  1005. config->WriteString(L"savedrefinefilter", L"");
  1006. break;
  1007. }
  1008. break;
  1009. case WM_DESTROY:
  1010. {
  1011. int update_needed = false;
  1012. int numFilters = config->ReadInt(L"media_numfilters",2);
  1013. int new_numFilters = 1;
  1014. if (IsDlgButtonChecked(hwndDlg,IDC_RADIO_FILTERS1)) new_numFilters = 1;
  1015. else if (IsDlgButtonChecked(hwndDlg,IDC_RADIO_FILTERS2)) new_numFilters = 2;
  1016. else if (IsDlgButtonChecked(hwndDlg,IDC_RADIO_FILTERS3)) new_numFilters = 3;
  1017. if (new_numFilters != numFilters) update_needed++;
  1018. config->WriteInt(L"media_numfilters",new_numFilters);
  1019. for(int i=0; i<3; i++) {
  1020. int id = (i==0)?IDC_COMBO_FILTER1:((i==1)?IDC_COMBO_FILTER2:IDC_COMBO_FILTER3);
  1021. int sel = SendDlgItemMessage(hwndDlg, id, CB_GETCURSEL, 0, 0);
  1022. wchar_t * x = (wchar_t*)SendDlgItemMessage(hwndDlg, id, CB_GETITEMDATA, sel, 0);
  1023. wchar_t name[20] = {0};
  1024. StringCchPrintf(name,20,L"media_filter%d",i);
  1025. extern wchar_t *GetDefFilter(int i,int n);
  1026. SendDlgItemMessage(hwndDlg,id,CB_SETCURSEL,0,0);
  1027. wchar_t* filterStr = config->ReadString(name,GetDefFilter(i,new_numFilters));
  1028. if(x && x != (wchar_t*)-1)
  1029. {
  1030. config->WriteString(name,x);
  1031. update_needed += (wcscmp(filterStr, x));
  1032. }
  1033. }
  1034. // only refresh the view if it is one of ours (is a bit silly
  1035. // otherwise) and also not refresh unless there was a change
  1036. // with the configDevice check to cope with going elsewhere
  1037. if (update_needed && ((configDevice && configDevice == currentViewedDevice) || IsWindow(hwndMediaView))) {
  1038. PostMessage(plugin.hwndLibraryParent, WM_USER + 30, 0, 0);
  1039. }
  1040. }
  1041. break;
  1042. }
  1043. return 0;
  1044. }
  1045. extern void unloadPlugin(PMPDevicePlugin *devplugin, int n=-1);
  1046. extern PMPDevicePlugin * loadPlugin(wchar_t * file);
  1047. HRESULT RemovePMPPlugin(LPCWSTR file, HINSTANCE hDllInstance) {
  1048. if(!hDllInstance) {
  1049. SHFILEOPSTRUCT op = {0};
  1050. wchar_t srcFile[MAX_PATH+1], *end;
  1051. op.wFunc = FO_DELETE;
  1052. StringCchCopyExW(srcFile, MAX_PATH, file, &end, 0, 0);
  1053. if (end) end[1]=0; // double null terminate
  1054. op.pFrom = srcFile;
  1055. op.fFlags=FOF_NOCONFIRMATION|FOF_NOCONFIRMMKDIR|FOF_SIMPLEPROGRESS|FOF_NORECURSION|FOF_NOERRORUI|FOF_SILENT;
  1056. return (!SHFileOperation(&op)? S_OK : E_FAIL);
  1057. }
  1058. else {
  1059. wchar_t buf[1024],
  1060. *ini = (wchar_t*)SendMessage(plugin.hwndWinampParent,WM_WA_IPC,0,IPC_GETINIFILEW);
  1061. GetModuleFileName(hDllInstance, buf, ARRAYSIZE(buf));
  1062. WritePrivateProfileString(L"winamp", L"remove_genplug", buf, ini);
  1063. WritePrivateProfileString(L"winamp", L"show_prefs", L"-1", ini);
  1064. PostMessage(plugin.hwndWinampParent, WM_USER, 0, IPC_RESTARTWINAMP);
  1065. return S_OK;
  1066. }
  1067. }
  1068. static bool pluginsLoaded;
  1069. INT_PTR CALLBACK config_dlgproc_plugins(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam) {
  1070. switch(uMsg)
  1071. {
  1072. case WM_INITDIALOG:
  1073. {
  1074. pluginsLoaded = false;
  1075. link_startsubclass(hwndDlg, IDC_PLUGINVERS);
  1076. {
  1077. HWND listWindow = GetDlgItem(hwndDlg, IDC_PLUGINSLIST);
  1078. if (NULL != listWindow)
  1079. {
  1080. RECT r = {0}, rc = {0};
  1081. GetWindowRect(listWindow, &r);
  1082. GetClientRect(listWindow, &r);
  1083. MapWindowPoints(listWindow, hwndDlg, (LPPOINT)&r, 2);
  1084. InflateRect(&r, 2, 2);
  1085. DestroyWindow(listWindow);
  1086. listWindow = CreateWindowEx(WS_EX_NOPARENTNOTIFY | WS_EX_CLIENTEDGE, WC_LISTVIEWW, L"",
  1087. WS_CHILD | WS_VISIBLE | WS_TABSTOP | LVS_REPORT | LVS_SINGLESEL |
  1088. LVS_SHOWSELALWAYS | LVS_SORTASCENDING | LVS_NOCOLUMNHEADER | LVS_NOSORTHEADER,
  1089. r.left, r.top, r.right - r.left, r.bottom - r.top,
  1090. hwndDlg, (HMENU)IDC_PLUGINSLIST, NULL, NULL);
  1091. SetWindowPos(listWindow, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOSENDCHANGING);
  1092. ListView_SetExtendedListViewStyleEx(listWindow, LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP, LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP);
  1093. SendMessage(listWindow, WM_SETFONT, SendMessage(hwndDlg, WM_GETFONT, 0, 0), FALSE);
  1094. LVCOLUMNW lvc = {0};
  1095. ListView_InsertColumn(listWindow, 0, &lvc);
  1096. ListView_InsertColumn(listWindow, 1, &lvc);
  1097. wchar_t buf[1024] = {0}, fn[MAX_PATH] = {0};
  1098. for (int x = 0; x < m_plugins.GetSize(); x ++)
  1099. {
  1100. PMPDevicePlugin * devplugin=(PMPDevicePlugin *)m_plugins.Get(x);
  1101. if (devplugin)
  1102. {
  1103. GetModuleFileNameW(devplugin->hDllInstance, fn, MAX_PATH);
  1104. PathStripPath(fn);
  1105. LVITEMW lvi = {LVIF_TEXT | LVIF_PARAM, x, 0};
  1106. lvi.pszText = devplugin->description;
  1107. lvi.lParam = x;
  1108. lvi.iItem = ListView_InsertItem(listWindow, &lvi);
  1109. lvi.mask = LVIF_TEXT;
  1110. lvi.iSubItem = 1;
  1111. lvi.pszText = fn;
  1112. ListView_SetItem(listWindow, &lvi);
  1113. }
  1114. }
  1115. WIN32_FIND_DATA d = {0};
  1116. wchar_t *pluginPath = (wchar_t*)SendMessage(plugin.hwndWinampParent, WM_WA_IPC, 0, IPC_GETPLUGINDIRECTORYW);
  1117. wchar_t dirstr[MAX_PATH] = {0};
  1118. PathCombine(dirstr, pluginPath, L"PMP_*.DLL");
  1119. HANDLE h = FindFirstFile(dirstr, &d);
  1120. if (h != INVALID_HANDLE_VALUE)
  1121. {
  1122. do
  1123. {
  1124. PathCombine(dirstr, pluginPath, d.cFileName);
  1125. HMODULE b = LoadLibraryEx(dirstr, NULL, LOAD_LIBRARY_AS_DATAFILE);
  1126. int x = 0;
  1127. for (; b && (x != m_plugins.GetSize()); x ++)
  1128. {
  1129. PMPDevicePlugin *devplugin = (PMPDevicePlugin *)m_plugins.Get(x);
  1130. if (devplugin->hDllInstance == b)
  1131. {
  1132. break;
  1133. }
  1134. }
  1135. if (x == m_plugins.GetSize() || !b)
  1136. {
  1137. LVITEMW lvi = {LVIF_TEXT | LVIF_PARAM, x, 0};
  1138. lvi.pszText = d.cFileName;
  1139. lvi.lParam = -2;
  1140. lvi.iItem = ListView_InsertItem(listWindow, &lvi);
  1141. lvi.mask = LVIF_TEXT;
  1142. lvi.iSubItem = 1;
  1143. lvi.pszText = WASABI_API_LNGSTRINGW(IDS_NOT_LOADED);
  1144. ListView_SetItem(listWindow, &lvi);
  1145. }
  1146. FreeLibrary(b);
  1147. }
  1148. while (FindNextFile(h, &d));
  1149. FindClose(h);
  1150. }
  1151. GetClientRect(listWindow, &r);
  1152. ListView_SetColumnWidth(listWindow, 1, LVSCW_AUTOSIZE);
  1153. ListView_SetColumnWidth(listWindow, 0, (r.right - r.left) - ListView_GetColumnWidth(listWindow, 1));
  1154. if (NULL != WASABI_API_APP)
  1155. WASABI_API_APP->DirectMouseWheel_EnableConvertToMouseWheel(listWindow, TRUE);
  1156. pluginsLoaded = true;
  1157. }
  1158. }
  1159. break;
  1160. }
  1161. case WM_NOTIFY:
  1162. {
  1163. LPNMHDR p = (LPNMHDR)lParam;
  1164. if (p->idFrom == IDC_PLUGINSLIST)
  1165. {
  1166. if (p->code == LVN_ITEMCHANGED)
  1167. {
  1168. LPNMLISTVIEW pnmv = (LPNMLISTVIEW)lParam;
  1169. LVITEM lvi = {LVIF_PARAM, pnmv->iItem};
  1170. if (ListView_GetItem(p->hwndFrom, &lvi) && (pnmv->uNewState & LVIS_SELECTED))
  1171. {
  1172. int loaded = (lvi.lParam != -2);
  1173. if (loaded)
  1174. {
  1175. PMPDevicePlugin *devplugin;
  1176. if (lvi.lParam >= 0 && lvi.lParam < m_plugins.GetSize() &&
  1177. (devplugin = (PMPDevicePlugin *)m_plugins.Get(lvi.lParam)))
  1178. {
  1179. // enables / disables the config button as applicable instead of the
  1180. // "This plug-in has no configuration implemented" message (opt-in)
  1181. EnableWindow(GetDlgItem(hwndDlg, IDC_CONFIGPLUGIN), (!devplugin->MessageProc(PMP_NO_CONFIG, 0, 0, 0)));
  1182. }
  1183. }
  1184. else
  1185. {
  1186. EnableWindow(GetDlgItem(hwndDlg, IDC_CONFIGPLUGIN), 0);
  1187. }
  1188. EnableWindow(GetDlgItem(hwndDlg, IDC_UNINSTALLPLUGIN), 1);
  1189. }
  1190. else
  1191. {
  1192. EnableWindow(GetDlgItem(hwndDlg, IDC_CONFIGPLUGIN), 0);
  1193. EnableWindow(GetDlgItem(hwndDlg, IDC_UNINSTALLPLUGIN), 0);
  1194. }
  1195. }
  1196. else if (p->code == NM_DBLCLK)
  1197. {
  1198. PostMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_CONFIGPLUGIN, 0), (LPARAM)GetDlgItem(hwndDlg, IDC_CONFIGPLUGIN));
  1199. }
  1200. }
  1201. else if (p->code == HDN_ITEMCHANGINGW)
  1202. {
  1203. if (pluginsLoaded)
  1204. {
  1205. #if defined(_WIN64)
  1206. SetWindowLong(hwndDlg, DWLP_MSGRESULT, TRUE);
  1207. #else
  1208. SetWindowLong(hwndDlg, DWL_MSGRESULT, TRUE);
  1209. #endif
  1210. return TRUE;
  1211. }
  1212. }
  1213. break;
  1214. }
  1215. case WM_DESTROY:
  1216. {
  1217. HWND listWindow = GetDlgItem(hwndDlg, IDC_PLUGINSLIST);
  1218. if (IsWindow(listWindow) && (NULL != WASABI_API_APP))
  1219. WASABI_API_APP->DirectMouseWheel_EnableConvertToMouseWheel(listWindow, FALSE);
  1220. }
  1221. break;
  1222. case WM_COMMAND:
  1223. switch(LOWORD(wParam))
  1224. {
  1225. case IDC_CONFIGPLUGIN:
  1226. {
  1227. if (IsWindowEnabled(GetDlgItem(hwndDlg, IDC_CONFIGPLUGIN)))
  1228. {
  1229. HWND listWindow = GetDlgItem(hwndDlg, IDC_PLUGINSLIST);
  1230. LVITEM lvi = {LVIF_PARAM, ListView_GetSelectionMark(listWindow)};
  1231. if (ListView_GetItem(listWindow, &lvi))
  1232. {
  1233. PMPDevicePlugin *devplugin;
  1234. if(lvi.lParam >= 0 && lvi.lParam < m_plugins.GetSize() && (devplugin=(PMPDevicePlugin *)m_plugins.Get(lvi.lParam)))
  1235. {
  1236. if(devplugin->MessageProc(PMP_CONFIG,(intptr_t)hwndDlg,0,0) == 0)
  1237. {
  1238. wchar_t titleStr[64] = {0};
  1239. MessageBox(hwndDlg,WASABI_API_LNGSTRINGW(IDS_PLUGIN_HAS_NO_CONFIG_IMPLEMENTED),
  1240. WASABI_API_LNGSTRINGW_BUF(IDS_DEVICE_PLUGINS,titleStr,64),0);
  1241. }
  1242. }
  1243. }
  1244. }
  1245. }
  1246. break;
  1247. case IDC_UNINSTALLPLUGIN:
  1248. {
  1249. if (IsWindowEnabled(GetDlgItem(hwndDlg, IDC_UNINSTALLPLUGIN)))
  1250. {
  1251. HWND listWindow = GetDlgItem(hwndDlg, IDC_PLUGINSLIST);
  1252. int which_sel = ListView_GetSelectionMark(listWindow);
  1253. LVITEM lvi = {LVIF_PARAM, which_sel};
  1254. if (ListView_GetItem(listWindow, &lvi))
  1255. {
  1256. PMPDevicePlugin *devplugin = 0;
  1257. wchar_t titleStr[32] = {0};
  1258. int msgBox = MessageBox(hwndDlg, WASABI_API_LNGSTRINGW(IDS_PERMANENTLY_UNINSTALL_THIS_PLUGIN),
  1259. WASABI_API_LNGSTRINGW_BUF(IDS_CONFIRMATION, titleStr, 32), MB_YESNO | MB_ICONEXCLAMATION);
  1260. if (lvi.lParam >= 0 && lvi.lParam <= m_plugins.GetSize() && (devplugin=(PMPDevicePlugin *)m_plugins.Get(lvi.lParam)) && msgBox == IDYES)
  1261. {
  1262. wchar_t buf[1024] = {0};
  1263. GetModuleFileName(devplugin->hDllInstance,buf,sizeof(buf)/sizeof(wchar_t));
  1264. int ret = PMP_PLUGIN_UNINSTALL_NOW;
  1265. int (*pr)(HINSTANCE hDllInst, HWND hwndDlg, int param);
  1266. *(void**)&pr = (void*)GetProcAddress(devplugin->hDllInstance,"winampUninstallPlugin");
  1267. if(pr) ret = pr(devplugin->hDllInstance,hwndDlg,0);
  1268. if(pr && ret == PMP_PLUGIN_UNINSTALL_NOW) { // dynamic unload
  1269. ListView_DeleteItem(listWindow, lvi.lParam);
  1270. unloadPlugin(devplugin,lvi.lParam);
  1271. // removing the plugin (bit convoluted to hopefully not cause crashes with dynamic removal)
  1272. // try to use the elevator to do this
  1273. IFileTypeRegistrar *registrar = (IFileTypeRegistrar*)SendMessage(plugin.hwndWinampParent,WM_WA_IPC,0,IPC_GET_FILEREGISTRAR_OBJECT);
  1274. if(registrar && (registrar != (IFileTypeRegistrar*)1)) {
  1275. if(registrar->DeleteItem(buf) != S_OK) {
  1276. // we don't always free by default as it can cause some crashes
  1277. FreeLibrary(devplugin->hDllInstance);
  1278. if(registrar->DeleteItem(buf) != S_OK) {
  1279. // all gone wrong so non-dynamic unload (restart winamp)
  1280. RemovePMPPlugin(buf, devplugin->hDllInstance);
  1281. }
  1282. }
  1283. registrar->Release();
  1284. }
  1285. // otherwise revert to a standard method
  1286. else {
  1287. if(RemovePMPPlugin(buf, 0) != S_OK){
  1288. // we don't always free by default as it can cause some crashes
  1289. FreeLibrary(devplugin->hDllInstance);
  1290. if(RemovePMPPlugin(buf, 0) != S_OK) {
  1291. // all gone wrong so non-dynamic unload (restart winamp)
  1292. RemovePMPPlugin(buf, devplugin->hDllInstance);
  1293. }
  1294. }
  1295. }
  1296. }
  1297. else if(!pr)
  1298. { // non-dynamic unload (restart winamp)
  1299. RemovePMPPlugin(buf,devplugin->hDllInstance);
  1300. }
  1301. }
  1302. // will cope with not loaded plug-ins so we can still remove them, etc
  1303. else if (lvi.lParam == -2 && msgBox == IDYES)
  1304. {
  1305. wchar_t buf[1024] = {0}, base[1024] = {0};
  1306. GetModuleFileName(plugin.hDllInstance,base,sizeof(base)/sizeof(wchar_t));
  1307. LVITEM lvi = {LVIF_TEXT, which_sel};
  1308. lvi.pszText = buf;
  1309. lvi.cchTextMax = ARRAYSIZE(buf);
  1310. ListView_GetItem(listWindow, &lvi);
  1311. wchar_t *p = wcschr(buf, L'.');
  1312. if (p && *p == L'.')
  1313. {
  1314. p += 4;
  1315. *p = 0;
  1316. PathRemoveFileSpec(base);
  1317. PathAppend(base, buf);
  1318. }
  1319. // try to use the elevator to do this
  1320. IFileTypeRegistrar *registrar = (IFileTypeRegistrar*)SendMessage(plugin.hwndWinampParent,WM_WA_IPC,0,IPC_GET_FILEREGISTRAR_OBJECT);
  1321. if(registrar && (registrar != (IFileTypeRegistrar*)1)) {
  1322. if(registrar->DeleteItem(base) != S_OK){
  1323. RemovePMPPlugin(base, 0);
  1324. }
  1325. else
  1326. ListView_DeleteItem(listWindow, which_sel);
  1327. registrar->Release();
  1328. }
  1329. // otherwise revert to a standard method
  1330. else {
  1331. RemovePMPPlugin(base, 0);
  1332. }
  1333. }
  1334. // resets the focus to the listbox so it'll keep ui response working
  1335. SetFocus(GetDlgItem(hwndDlg, IDC_PLUGINSLIST));
  1336. }
  1337. }
  1338. }
  1339. break;
  1340. case IDC_PLUGINVERS:
  1341. myOpenURLWithFallback(hwndDlg, L"http://www.google.com/search?q=Winamp+Portable+Plugins",L"http://www.google.com/search?q=Winamp+Portable+Plugins");
  1342. break;
  1343. }
  1344. break;
  1345. }
  1346. link_handledraw(hwndDlg,uMsg,wParam,lParam);
  1347. return 0;
  1348. }
  1349. void myOpenURLWithFallback(HWND hwnd, wchar_t *loc, wchar_t *fallbackLoc)
  1350. {
  1351. bool override=false;
  1352. if (loc)
  1353. {
  1354. WASABI_API_SYSCB->syscb_issueCallback(SysCallback::BROWSER, BrowserCallback::ONOPENURL, reinterpret_cast<intptr_t>(loc), reinterpret_cast<intptr_t>(&override));
  1355. }
  1356. if (!override && fallbackLoc)
  1357. ShellExecuteW(hwnd, L"open", fallbackLoc, NULL, NULL, SW_SHOWNORMAL);
  1358. }
  1359. static HCURSOR link_hand_cursor;
  1360. LRESULT link_handlecursor(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1361. {
  1362. LRESULT ret = CallWindowProcW((WNDPROC)GetPropW(hwndDlg, L"link_proc"), hwndDlg, uMsg, wParam, lParam);
  1363. // override the normal cursor behaviour so we have a hand to show it is a link
  1364. if(uMsg == WM_SETCURSOR)
  1365. {
  1366. if((HWND)wParam == hwndDlg)
  1367. {
  1368. if(!link_hand_cursor)
  1369. {
  1370. link_hand_cursor = LoadCursor(NULL, IDC_HAND);
  1371. }
  1372. SetCursor(link_hand_cursor);
  1373. return TRUE;
  1374. }
  1375. }
  1376. return ret;
  1377. }
  1378. void link_startsubclass(HWND hwndDlg, UINT id){
  1379. HWND ctrl = GetDlgItem(hwndDlg, id);
  1380. SetPropW(ctrl, L"link_proc",
  1381. (HANDLE)SetWindowLongPtrW(ctrl, GWLP_WNDPROC, (LONG_PTR)link_handlecursor));
  1382. }
  1383. static void link_handledraw(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1384. {
  1385. if (uMsg == WM_DRAWITEM)
  1386. {
  1387. DRAWITEMSTRUCT *di = (DRAWITEMSTRUCT *)lParam;
  1388. if (di->CtlType == ODT_BUTTON)
  1389. {
  1390. wchar_t wt[123] = {0};
  1391. int y;
  1392. RECT r;
  1393. HPEN hPen, hOldPen;
  1394. GetDlgItemText(hwndDlg, wParam, wt, sizeof(wt)/sizeof(wchar_t));
  1395. // draw text
  1396. SetTextColor(di->hDC, (di->itemState & ODS_SELECTED) ? RGB(220, 0, 0) : RGB(0, 0, 220));
  1397. r = di->rcItem;
  1398. r.left += 2;
  1399. DrawText(di->hDC, wt, -1, &r, DT_VCENTER | DT_SINGLELINE);
  1400. memset(&r, 0, sizeof(r));
  1401. DrawText(di->hDC, wt, -1, &r, DT_SINGLELINE | DT_CALCRECT);
  1402. // draw underline
  1403. y = di->rcItem.bottom - ((di->rcItem.bottom - di->rcItem.top) - (r.bottom - r.top)) / 2 - 1;
  1404. hPen = CreatePen(PS_SOLID, 0, (di->itemState & ODS_SELECTED) ? RGB(220, 0, 0) : RGB(0, 0, 220));
  1405. hOldPen = (HPEN) SelectObject(di->hDC, hPen);
  1406. MoveToEx(di->hDC, di->rcItem.left + 2, y, NULL);
  1407. LineTo(di->hDC, di->rcItem.right + 2 - ((di->rcItem.right - di->rcItem.left) - (r.right - r.left)), y);
  1408. SelectObject(di->hDC, hOldPen);
  1409. DeleteObject(hPen);
  1410. }
  1411. }
  1412. }