navigation.cpp 33 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472
  1. #include "main.h"
  2. #include "./navigation.h"
  3. #include "./resource.h"
  4. #include "./api__ml_online.h"
  5. #include "./local_menu.h"
  6. #include "./commands.h"
  7. #include "./config.h"
  8. #include "../omBrowser/browserView.h"
  9. #include "../winamp/wa_ipc.h"
  10. #include "./serviceHost.h"
  11. #include "./serviceHelper.h"
  12. #include "./browserEvent.h"
  13. #include <ifc_omservice.h>
  14. #include <ifc_omserviceeditor.h>
  15. #include <storageIni.h>
  16. #include <ifc_omserviceenum.h>
  17. #include <ifc_mlnavigationhelper.h>
  18. #include <ifc_omserviceeventmngr.h>
  19. #include <ifc_ombrowserwndmngr.h>
  20. #include <ifc_ombrowserwndenum.h>
  21. #include <ifc_ombrowsereventmngr.h>
  22. #include "../../General/gen_ml/menu.h"
  23. #include "../../General/gen_ml/ml_ipc_0313.h"
  24. #include <vector>
  25. #include "../nu/sort.h"
  26. #include <shlwapi.h>
  27. #include <strsafe.h>
  28. #include <algorithm>
  29. #define NAVITEM_PREFIX L"om_svc_"
  30. #define E_NAVITEM_UNKNOWN E_NOINTERFACE
  31. typedef struct __NAVASYNCPARAM
  32. {
  33. Navigation *instance;
  34. NavigationCallback callback;
  35. ULONG_PTR param;
  36. }NAVASYNCPARAM;
  37. static BOOL Navigation_CheckInvariantName(LPCWSTR pszInvarian)
  38. {
  39. INT cchInvariant = (NULL != pszInvarian) ? lstrlen(pszInvarian) : 0;
  40. INT cchPrefix = ARRAYSIZE(NAVITEM_PREFIX) - 1;
  41. return (cchInvariant > cchPrefix &&
  42. CSTR_EQUAL == CompareString(CSTR_INVARIANT, 0, NAVITEM_PREFIX, cchPrefix, pszInvarian, cchPrefix));
  43. }
  44. Navigation::Navigation()
  45. : ref(1), cookie(0), hRoot(NULL), hLibrary(NULL)
  46. {
  47. }
  48. Navigation::~Navigation()
  49. {
  50. }
  51. HRESULT Navigation::CreateInstance(Navigation **instance)
  52. {
  53. if (NULL == instance) return E_POINTER;
  54. HRESULT hr;
  55. Navigation *navigation = new Navigation();
  56. if (NULL != navigation)
  57. {
  58. hr = navigation->Initialize();
  59. if (FAILED(hr))
  60. {
  61. navigation->Release();
  62. navigation = NULL;
  63. }
  64. }
  65. else
  66. {
  67. hr = E_OUTOFMEMORY;
  68. }
  69. *instance = navigation;
  70. return hr;
  71. }
  72. size_t Navigation::AddRef()
  73. {
  74. return InterlockedIncrement((LONG*)&ref);
  75. }
  76. size_t Navigation::Release()
  77. {
  78. if (0 == ref)
  79. return ref;
  80. LONG r = InterlockedDecrement((LONG*)&ref);
  81. if (0 == r)
  82. delete(this);
  83. return r;
  84. }
  85. int Navigation::QueryInterface(GUID interface_guid, void **object)
  86. {
  87. if (NULL == object) return E_POINTER;
  88. if (IsEqualIID(interface_guid, IFC_MlNavigationCallback))
  89. *object = static_cast<ifc_mlnavigationcallback*>(this);
  90. else
  91. {
  92. *object = NULL;
  93. return E_NOINTERFACE;
  94. }
  95. if (NULL == *object)
  96. return E_UNEXPECTED;
  97. AddRef();
  98. return S_OK;
  99. }
  100. HRESULT Navigation::Initialize()
  101. {
  102. hLibrary = Plugin_GetLibrary();
  103. if (NULL == hLibrary) return E_UNEXPECTED;
  104. if (0 == cookie)
  105. {
  106. ifc_mlnavigationhelper *navHelper;
  107. if (NULL != OMUTILITY && SUCCEEDED(OMUTILITY->GetMlNavigationHelper(Plugin_GetLibrary(), &navHelper)))
  108. {
  109. navHelper->RegisterCallback(this, &cookie);
  110. navHelper->Release();
  111. }
  112. }
  113. ifc_omservice *service;
  114. MLNavCtrl_BeginUpdate(hLibrary, NUF_LOCK_TOP);
  115. // TODO make thie configurable?
  116. if (SUCCEEDED(ServiceHelper_Create(ROOTSERVICE_ID, MAKEINTRESOURCE(IDS_ONLINE_SERVICES),
  117. NULL, L"http://client.winamp.com/services", SVCF_SPECIAL | SVCF_SUBSCRIBED, 1, FALSE, &service)))
  118. {
  119. hRoot = CreateItemInt(NULL, service);
  120. service->Release();
  121. }
  122. if (NULL == hRoot)
  123. {
  124. MLNavCtrl_EndUpdate(hLibrary);
  125. return E_FAIL;
  126. }
  127. ifc_omserviceenum *enumerator;
  128. if (SUCCEEDED(ServiceHelper_Load(&enumerator)))
  129. {
  130. ifc_omservice *service;
  131. std::vector<ifc_omservice*> serviceList;
  132. while (S_OK == enumerator->Next(1, &service, NULL))
  133. {
  134. if (S_OK == ServiceHelper_IsSubscribed(service))
  135. {
  136. serviceList.push_back(service);
  137. }
  138. else
  139. service->Release();
  140. }
  141. enumerator->Release();
  142. size_t count = serviceList.size();
  143. Order(serviceList);
  144. for(size_t i =0; i < count; i++)
  145. {
  146. service = serviceList[i];
  147. CreateItemInt(hRoot, service);
  148. service->Release();
  149. }
  150. }
  151. MLNavCtrl_EndUpdate(hLibrary);
  152. return S_OK;
  153. }
  154. HRESULT Navigation::Finish()
  155. {
  156. if (0 != cookie)
  157. {
  158. ifc_mlnavigationhelper *navHelper;
  159. if (NULL != OMUTILITY && SUCCEEDED(OMUTILITY->GetMlNavigationHelper(Plugin_GetLibrary(), &navHelper)))
  160. {
  161. navHelper->UnregisterCallback(cookie);
  162. navHelper->Release();
  163. }
  164. }
  165. if (NULL != OMBROWSERMNGR)
  166. {
  167. OMBROWSERMNGR->Finish();
  168. }
  169. return S_OK;
  170. }
  171. HRESULT Navigation::SaveOrder()
  172. {
  173. if (NULL == hRoot || NULL == hLibrary)
  174. return E_UNEXPECTED;
  175. LPSTR buffer = NULL;
  176. INT count = MLNavItem_GetChildrenCount(hLibrary, hRoot);
  177. if (count > 0)
  178. {
  179. size_t bufferMax = 11 * count;
  180. buffer = Plugin_MallocAnsiString(bufferMax);
  181. if (NULL == buffer) return E_OUTOFMEMORY;
  182. *buffer = '\0';
  183. LPSTR cursor = buffer;
  184. size_t remaining = bufferMax;
  185. NAVITEM item;
  186. item.cbSize = sizeof(item);
  187. item.mask = NIMF_PARAM;
  188. item.hItem = MLNavItem_GetChild(hLibrary, hRoot);
  189. while (NULL != item.hItem)
  190. {
  191. if (FALSE != MLNavItem_GetInfo(hLibrary, &item))
  192. {
  193. ifc_omservice *service = (ifc_omservice*)item.lParam;
  194. if (NULL != service)
  195. {
  196. UINT serviceFlags;
  197. if (SUCCEEDED(service->GetFlags(&serviceFlags)) &&
  198. 0 == (SVCF_SPECIAL & serviceFlags))
  199. {
  200. if (cursor == buffer ||
  201. SUCCEEDED(StringCchCopyExA(cursor, remaining, ";", &cursor, &remaining, STRSAFE_NULL_ON_FAILURE)))
  202. {
  203. StringCchPrintfExA(cursor, remaining, &cursor, &remaining, STRSAFE_NULL_ON_FAILURE, "%d", service->GetId());
  204. }
  205. }
  206. }
  207. }
  208. item.hItem = MLNavItem_GetNext(hLibrary, item.hItem);
  209. }
  210. }
  211. Config_WriteStr("Navigation", "order", buffer);
  212. Plugin_FreeAnsiString(buffer);
  213. return S_OK;
  214. }
  215. //static int __fastcall Navigation_OrderComparer(const void *elem1, const void *elem2, const void *context)
  216. //{
  217. // std::vector<UINT> *orderList = (std::vector<UINT>*)context;
  218. //
  219. // UINT serviceId;
  220. // size_t index1, index2;
  221. // size_t count = orderList->size();
  222. //
  223. // serviceId = (*(ifc_omservice**)elem1)->GetId();
  224. // for (index1 = 0; index1 < count && serviceId != orderList->at(index1); index1++);
  225. //
  226. // serviceId = (*(ifc_omservice**)elem2)->GetId();
  227. // for (index2 = 0; index2 < count && serviceId != orderList->at(index2); index2++);
  228. //
  229. // return (INT)(index1 - index2);
  230. //}
  231. class Navigation_OrderComparer
  232. {
  233. public:
  234. Navigation_OrderComparer(const void* ctx)
  235. : context(ctx)
  236. {
  237. }
  238. bool operator()(const void* elem1, const void* elem2)
  239. {
  240. std::vector<UINT>* orderList = (std::vector<UINT>*)context;
  241. UINT serviceId;
  242. size_t index1, index2;
  243. size_t count = orderList->size();
  244. serviceId = ((ifc_omservice*)elem1)->GetId();
  245. for (index1 = 0; index1 < count && serviceId != orderList->at(index1); index1++);
  246. serviceId = ((ifc_omservice*)elem2)->GetId();
  247. for (index2 = 0; index2 < count && serviceId != orderList->at(index2); index2++);
  248. return (INT)(index1 - index2) < 0;
  249. }
  250. private:
  251. const void* context;
  252. };
  253. HRESULT Navigation::Order(std::vector<ifc_omservice*> &list)
  254. {
  255. size_t listSize = list.size();
  256. if (listSize < 2)
  257. return S_FALSE;
  258. //if (NULL == list) return E_INVALIDARG;
  259. size_t bufferMax = 16384;
  260. LPSTR buffer = Plugin_MallocAnsiString(bufferMax);
  261. if (NULL == buffer) return E_OUTOFMEMORY;
  262. UINT len = Config_ReadStr("Navigation", "order", NULL, buffer, (UINT)bufferMax);
  263. std::vector<UINT> orderList;
  264. LPCSTR end = buffer + len;
  265. LPCSTR block = buffer;
  266. LPCSTR cursor = block;
  267. for(;;)
  268. {
  269. if (cursor == end || ';' == *cursor)
  270. {
  271. if (block != cursor)
  272. {
  273. INT serviceId;
  274. if (FALSE != StrToIntExA(block, STIF_DEFAULT, &serviceId))
  275. orderList.push_back(serviceId);
  276. }
  277. if (cursor == end) break;
  278. cursor++;
  279. block = cursor;
  280. }
  281. cursor++;
  282. }
  283. if (0 != orderList.size())
  284. {
  285. //nu::qsort(list, listSize, sizeof(ifc_omservice*), &orderList, Navigation_OrderComparer);
  286. std::sort(list.begin(), list.end(), Navigation_OrderComparer(&orderList));
  287. }
  288. Plugin_FreeAnsiString(buffer);
  289. return S_OK;
  290. }
  291. typedef struct __IMAGEAPCPARAM
  292. {
  293. LPWSTR name;
  294. INT index;
  295. } IMAGEAPCPARAM;
  296. static void CALLBACK Navigtaion_ImageChangedApc(Navigation *instance, ULONG_PTR param)
  297. {
  298. IMAGEAPCPARAM *image = (IMAGEAPCPARAM*)param;
  299. if (NULL == image) return;
  300. instance->ImageChanged(image->name, image->index);
  301. Plugin_FreeString(image->name);
  302. free(image);
  303. }
  304. void Navigation::ImageChanged(LPCWSTR pszName, INT index)
  305. {
  306. if (NULL == hRoot || NULL == hLibrary || NULL == pszName)
  307. return;
  308. DWORD libraryTID = GetWindowThreadProcessId(hLibrary, NULL);
  309. DWORD currentTID = GetCurrentThreadId();
  310. if (libraryTID != currentTID)
  311. {
  312. if (NULL != OMUTILITY)
  313. {
  314. IMAGEAPCPARAM *param = (IMAGEAPCPARAM*)calloc(1, sizeof(IMAGEAPCPARAM));
  315. if (NULL != param)
  316. {
  317. param->name = Plugin_CopyString(pszName);
  318. param->index = index;
  319. if (FAILED(PostMainThreadCallback(Navigtaion_ImageChangedApc, (ULONG_PTR)param)))
  320. {
  321. free(param);
  322. }
  323. }
  324. }
  325. return;
  326. }
  327. WCHAR szBuffer[2048] = {0};
  328. NAVITEM item = {0};
  329. item.cbSize = sizeof(item);
  330. item.mask = NIMF_TEXTINVARIANT | NIMF_PARAM;
  331. item.pszInvariant = szBuffer;
  332. item.cchInvariantMax = ARRAYSIZE(szBuffer);
  333. item.hItem = hRoot;
  334. while (NULL != item.hItem)
  335. {
  336. if (FALSE != MLNavItem_GetInfo(hLibrary, &item) &&
  337. FALSE != Navigation_CheckInvariantName(item.pszInvariant))
  338. {
  339. ifc_omservice *service = (ifc_omservice*)item.lParam;
  340. if (NULL != service &&
  341. SUCCEEDED(service->GetIcon(szBuffer, ARRAYSIZE(szBuffer))) &&
  342. CSTR_EQUAL == CompareString(CSTR_INVARIANT, NORM_IGNORECASE, szBuffer, -1, pszName, -1))
  343. {
  344. item.iImage = index;
  345. item.iSelectedImage = index;
  346. item.mask = NIMF_IMAGE | NIMF_IMAGESEL;
  347. MLNavItem_SetInfo(hLibrary, &item);
  348. return;
  349. }
  350. }
  351. item.hItem = (HNAVITEM)SENDMLIPC(hLibrary,
  352. (item.hItem == hRoot) ? ML_IPC_NAVITEM_GETCHILD : ML_IPC_NAVITEM_GETNEXT,
  353. (WPARAM)item.hItem);
  354. }
  355. }
  356. BOOL Navigation::ProcessMessage(INT msg, INT_PTR param1, INT_PTR param2, INT_PTR param3, INT_PTR *result)
  357. {
  358. if (msg < ML_MSG_TREE_BEGIN || msg > ML_MSG_TREE_END)
  359. return FALSE;
  360. HRESULT hr;
  361. switch(msg)
  362. {
  363. case ML_MSG_TREE_ONCREATEVIEW:
  364. {
  365. HWND hView;
  366. hr = OnCreateView(GetMessageItem(msg, param1), (HWND)param2, &hView);
  367. *result = (SUCCEEDED(hr)) ? (INT_PTR)hView : NULL;
  368. }
  369. return TRUE;
  370. case ML_MSG_NAVIGATION_CONTEXTMENU:
  371. hr = OnContextMenu(GetMessageItem(msg, param1), (HWND)param2, MAKEPOINTS(param3));
  372. *result = SUCCEEDED(hr);
  373. return TRUE;
  374. case ML_MSG_NAVIGATION_ONDELETE:
  375. hr = OnDeleteItem(GetMessageItem(msg, param1));
  376. *result = SUCCEEDED(hr);
  377. return TRUE;
  378. case ML_MSG_NAVIGATION_ONENDTITLEEDIT:
  379. hr = OnEndTitleEdit(GetMessageItem(msg, param1), (LPCWSTR)param2);
  380. *result = SUCCEEDED(hr);
  381. return TRUE;
  382. case ML_MSG_TREE_ONKEYDOWN:
  383. hr = OnKeyDown(GetMessageItem(msg, param1), (NMTVKEYDOWN*)param2);
  384. *result = SUCCEEDED(hr);
  385. return TRUE;
  386. case ML_MSG_NAVIGATION_ONDESTROY:
  387. OnControlDestroy();
  388. *result = 0;
  389. return TRUE;
  390. }
  391. return FALSE;
  392. }
  393. HNAVITEM Navigation::GetActive(ifc_omservice **serviceOut)
  394. {
  395. ifc_omservice *service;
  396. HNAVITEM hActive = (NULL != hLibrary) ? MLNavCtrl_GetSelection(hLibrary) : NULL;
  397. if (NULL == hActive || FAILED(GetService(hActive, &service)))
  398. {
  399. hActive = NULL;
  400. service = NULL;
  401. }
  402. if (NULL != serviceOut)
  403. *serviceOut = service;
  404. else if (NULL != service)
  405. service->Release();
  406. return hActive;
  407. }
  408. HWND Navigation::GetActiveView(ifc_omservice **serviceOut)
  409. {
  410. HWND hView = (NULL != hLibrary) ? ((HWND)SENDMLIPC(hLibrary, ML_IPC_GETCURRENTVIEW, 0)) : NULL;
  411. if (NULL != hView)
  412. {
  413. WCHAR szBuffer[128] = {0};
  414. if (!GetClassName(hView, szBuffer, ARRAYSIZE(szBuffer)) ||
  415. CSTR_EQUAL != CompareStringW(CSTR_INVARIANT, NORM_IGNORECASE, szBuffer, -1,
  416. L"Nullsoft_omBrowserView", -1))
  417. {
  418. hView = NULL;
  419. }
  420. }
  421. ifc_omservice *service;
  422. if (NULL == hView || FALSE == BrowserView_GetService(hView, &service))
  423. {
  424. hView = NULL;
  425. service = NULL;
  426. }
  427. if (NULL != serviceOut)
  428. *serviceOut = service;
  429. else if (NULL != service)
  430. service->Release();
  431. return hView;
  432. }
  433. HRESULT Navigation::SelectItem(HNAVITEM hItem, LPCWSTR pszUrl)
  434. {
  435. if (NULL == hItem) return E_INVALIDARG;
  436. ifc_omservice *service;
  437. HRESULT hr = GetService(hItem, &service);
  438. if (FAILED(hr)) return hr;
  439. hr = SelectItemInt(hItem, service->GetId(), pszUrl);
  440. service->Release();
  441. return hr;
  442. }
  443. HRESULT Navigation::DeleteItem(HNAVITEM hItem)
  444. {
  445. if (NULL == hItem) return E_INVALIDARG;
  446. if (NULL == hLibrary) return E_UNEXPECTED;
  447. ifc_omservice *service;
  448. if (FAILED(GetService(hItem, &service)))
  449. return E_FAIL;
  450. HRESULT hr;
  451. UINT serviceFlags;
  452. if (FAILED(service->GetFlags(&serviceFlags))) serviceFlags = 0;
  453. if (0 == (SVCF_SPECIAL & serviceFlags))
  454. {
  455. MLNavCtrl_BeginUpdate(hLibrary, 0);
  456. HNAVITEM hSelection = MLNavCtrl_GetSelection(hLibrary);
  457. if (hSelection == hItem)
  458. {
  459. HNAVITEM hNext = MLNavItem_GetNext(hLibrary, hItem);
  460. if (NULL == hNext)
  461. hNext = MLNavItem_GetPrevious(hLibrary, hItem);
  462. if (NULL != hNext)
  463. {
  464. MLNavItem_Select(hLibrary, hNext);
  465. }
  466. }
  467. BOOL result = MLNavCtrl_DeleteItem(hLibrary, hItem);
  468. hr = (FALSE != result) ? S_OK : E_FAIL;
  469. MLNavCtrl_EndUpdate(hLibrary);
  470. }
  471. else
  472. {
  473. hr = E_FAIL;
  474. }
  475. service->Release();
  476. return hr;
  477. }
  478. HRESULT Navigation::DeleteAll()
  479. {
  480. if (NULL == hRoot || NULL == hLibrary) return E_UNEXPECTED;
  481. std::vector<HNAVITEM> itemList;
  482. HNAVITEM hItem = MLNavItem_GetChild(hLibrary, hRoot);
  483. while (NULL != hItem)
  484. {
  485. itemList.push_back(hItem);
  486. hItem = MLNavItem_GetNext(hLibrary, hItem);
  487. }
  488. MLNavCtrl_BeginUpdate(hLibrary, 0);
  489. NAVITEM item;
  490. item.cbSize = sizeof(item);
  491. item.mask = NIMF_PARAM;
  492. size_t index = itemList.size();
  493. while(index--)
  494. {
  495. item.hItem = itemList[index];
  496. if (FALSE != MLNavItem_GetInfo(hLibrary, &item))
  497. {
  498. ifc_omservice *service = (ifc_omservice*)item.lParam;
  499. if (NULL != service)
  500. {
  501. service->AddRef();
  502. UINT serviceFlags;
  503. if (SUCCEEDED(service->GetFlags(&serviceFlags)) &&
  504. 0 == (SVCF_SPECIAL & serviceFlags) &&
  505. FALSE != MLNavCtrl_DeleteItem(hLibrary, item.hItem))
  506. {
  507. }
  508. service->Release();
  509. }
  510. }
  511. }
  512. MLNavCtrl_EndUpdate(hLibrary);
  513. return S_OK;
  514. }
  515. HRESULT Navigation::InitializeBrowser()
  516. {
  517. if (NULL == OMBROWSERMNGR)
  518. return E_UNEXPECTED;
  519. HWND hWinamp = Plugin_GetWinamp();
  520. HRESULT hr = OMBROWSERMNGR->Initialize(NULL, hWinamp);
  521. if (SUCCEEDED(hr))
  522. {
  523. if (S_OK == hr)
  524. {
  525. ifc_ombrowsereventmngr *eventManager;
  526. if (SUCCEEDED(OMBROWSERMNGR->QueryInterface(IFC_OmBrowserEventManager, (void**)&eventManager)))
  527. {
  528. BrowserEvent *eventHandler;
  529. if (SUCCEEDED(BrowserEvent::CreateInstance(&eventHandler)))
  530. {
  531. eventManager->RegisterHandler(eventHandler);
  532. eventHandler->Release();
  533. }
  534. eventManager->Release();
  535. }
  536. }
  537. }
  538. return hr;
  539. }
  540. HRESULT Navigation::CreatePopup(HNAVITEM hItem, HWND *hwnd)
  541. {
  542. if (NULL == hwnd) return E_POINTER;
  543. *hwnd = NULL;
  544. if (NULL == hLibrary) return E_UNEXPECTED;
  545. if (NULL == hItem) return E_INVALIDARG;
  546. HRESULT hr;
  547. ifc_omservice *service;
  548. hr = GetService(hItem, &service);
  549. if (SUCCEEDED(hr))
  550. {
  551. HWND hWinamp = Plugin_GetWinamp();
  552. hr = InitializeBrowser();
  553. if (SUCCEEDED(hr))
  554. {
  555. RECT rect;
  556. HWND hFrame = (HWND)SENDMLIPC(hLibrary, ML_IPC_GETCURRENTVIEW, 0);
  557. if (NULL == hFrame) hFrame = hLibrary;
  558. if (NULL == hFrame || FALSE == GetWindowRect(hFrame, &rect))
  559. {
  560. hr = E_FAIL;
  561. }
  562. if (SUCCEEDED(hr))
  563. {
  564. rect.left += 16;
  565. rect.top += 16;
  566. hr = OMBROWSERMNGR->CreatePopup(service, rect.left, rect.top,
  567. rect.right - rect.left, rect.bottom - rect.top, hWinamp, NULL, 0, hwnd);
  568. }
  569. }
  570. service->Release();
  571. }
  572. return hr;
  573. }
  574. static void CALLBACK Navigation_AsyncCallback(ULONG_PTR data)
  575. {
  576. NAVASYNCPARAM *async = (NAVASYNCPARAM*)data;
  577. if (NULL == async) return;
  578. async->callback(async->instance, async->param);
  579. if (NULL != async->instance)
  580. async->instance->Release();
  581. free(async);
  582. }
  583. HRESULT Navigation::PostMainThreadCallback(NavigationCallback callback, ULONG_PTR param)
  584. {
  585. if (NULL == callback)
  586. return E_INVALIDARG;
  587. NAVASYNCPARAM *async = (NAVASYNCPARAM*)calloc(1, sizeof(NAVASYNCPARAM));
  588. if (NULL == async) return E_OUTOFMEMORY;
  589. async->instance = this;
  590. async->callback = callback;
  591. async->param = param;
  592. this->AddRef();
  593. HRESULT hr;
  594. if (NULL == OMUTILITY)
  595. hr = E_FAIL;
  596. else
  597. {
  598. hr = OMUTILITY->PostMainThreadCallback(Navigation_AsyncCallback, (ULONG_PTR)async);
  599. if (FAILED(hr))
  600. {
  601. Release();
  602. free(async);
  603. }
  604. }
  605. return hr;
  606. }
  607. static void CALLBACK Navigation_CreateItemAsyncCallback(Navigation *instance, ULONG_PTR param)
  608. {
  609. ifc_omservice *service= (ifc_omservice*)param;
  610. if (NULL != service)
  611. {
  612. if (NULL != instance)
  613. instance->CreateItem(service);
  614. service->Release();
  615. }
  616. }
  617. HRESULT Navigation::CreateItemAsync(ifc_omservice *service)
  618. {
  619. if (NULL == service)
  620. return E_INVALIDARG;;
  621. service->AddRef();
  622. HRESULT hr = PostMainThreadCallback(Navigation_CreateItemAsyncCallback, (ULONG_PTR)service);
  623. if (FAILED(hr))
  624. service->Release();
  625. return hr;
  626. }
  627. HRESULT Navigation::GetService(HNAVITEM hItem, ifc_omservice **service)
  628. {
  629. WCHAR szBuffer[64] = {0};
  630. if (NULL == service) return E_POINTER;
  631. *service = NULL;
  632. if (NULL == hLibrary || NULL == hItem)
  633. return E_INVALIDARG;
  634. NAVITEM itemInfo;
  635. itemInfo.cbSize = sizeof(NAVITEM);
  636. itemInfo.hItem = hItem;
  637. itemInfo.pszInvariant = szBuffer;
  638. itemInfo.cchInvariantMax = ARRAYSIZE(szBuffer);
  639. itemInfo.mask = NIMF_PARAM | NIMF_TEXTINVARIANT;
  640. if (FALSE == MLNavItem_GetInfo(hLibrary, &itemInfo))
  641. return E_FAIL;
  642. if (FALSE == Navigation_CheckInvariantName(szBuffer))
  643. return E_NAVITEM_UNKNOWN;
  644. *service = (ifc_omservice*)itemInfo.lParam;
  645. (*service)->AddRef();
  646. return S_OK;
  647. }
  648. static void CALLBACK Navigtaion_UpdateServiceApc(Dispatchable *object, ULONG_PTR param1, ULONG_PTR param2)
  649. {
  650. Navigation *navigation = (Navigation*)object;
  651. if (NULL != navigation)
  652. {
  653. ifc_omservice *service = (ifc_omservice*)param1;
  654. navigation->UpdateService(service, (UINT)param2);
  655. if (NULL != service) service->Release();
  656. }
  657. }
  658. HRESULT Navigation::UpdateService(ifc_omservice *service, UINT modifiedFlags)
  659. {
  660. if (NULL == hLibrary) return E_UNEXPECTED;
  661. DWORD libraryTID = GetWindowThreadProcessId(hLibrary, NULL);
  662. DWORD currentTID = GetCurrentThreadId();
  663. if (libraryTID != currentTID)
  664. {
  665. if (NULL != OMUTILITY)
  666. {
  667. service->AddRef();
  668. if (FAILED(OMUTILITY->PostMainThreadCallback2(Navigtaion_UpdateServiceApc, this, (ULONG_PTR)service, (ULONG_PTR)modifiedFlags)))
  669. service->Release();
  670. }
  671. return E_PENDING;
  672. }
  673. HNAVITEM hItem = FindService(service->GetId(), NULL);
  674. if (NULL == hItem)
  675. return E_FAIL;
  676. if (0 != (ifc_omserviceeditor::modifiedFlags & modifiedFlags) &&
  677. S_FALSE == ServiceHelper_IsSubscribed(service))
  678. {
  679. DeleteItem(hItem);
  680. return S_OK;
  681. }
  682. NAVITEM itemInfo;
  683. itemInfo.cbSize = sizeof(NAVITEM);
  684. itemInfo.hItem = hItem;
  685. itemInfo.mask = NIMF_IMAGE;
  686. if (FALSE == MLNavItem_GetInfo(hLibrary, &itemInfo))
  687. itemInfo.iImage= -1;
  688. itemInfo.mask = 0;
  689. WCHAR szName[512] = {0};
  690. if (0 != (ifc_omserviceeditor::modifiedName & modifiedFlags) &&
  691. SUCCEEDED(service->GetName(szName, ARRAYSIZE(szName))))
  692. {
  693. itemInfo.mask |= NIMF_TEXT;
  694. itemInfo.pszText = szName;
  695. }
  696. if (0 != (ifc_omserviceeditor::modifiedIcon & modifiedFlags))
  697. {
  698. ifc_mlnavigationhelper *navHelper;
  699. if (SUCCEEDED(OMUTILITY->GetMlNavigationHelper(Plugin_GetLibrary(), &navHelper)))
  700. {
  701. INT iImage;
  702. WCHAR szIcon[1024] = {0};
  703. if (FAILED(service->GetIcon(szIcon, ARRAYSIZE(szIcon))) ||
  704. FAILED(navHelper->QueryIndex(szIcon, &iImage, NULL)))
  705. {
  706. iImage = -1;
  707. }
  708. if (itemInfo.iImage != iImage)
  709. {
  710. itemInfo.mask |= NIMF_IMAGE | NIMF_IMAGESEL;
  711. itemInfo.iImage = iImage;
  712. itemInfo.iSelectedImage = iImage;
  713. }
  714. navHelper->Release();
  715. }
  716. }
  717. if (0 != itemInfo.mask)
  718. {
  719. if (FALSE == MLNavItem_SetInfo(hLibrary, &itemInfo))
  720. return E_FAIL;
  721. }
  722. NAVITEMINAVLIDATE invalidate;
  723. invalidate.hItem = hItem;
  724. invalidate.fErase = FALSE;
  725. invalidate.prc = NULL;
  726. MLNavItem_Invalidate(hLibrary, &invalidate);
  727. return S_OK;
  728. }
  729. HNAVITEM Navigation::FindService(UINT serviceId, ifc_omservice **serviceOut)
  730. {
  731. if (NULL == hRoot || NULL == hLibrary)
  732. {
  733. if (NULL != serviceOut) *serviceOut = NULL;
  734. return NULL;
  735. }
  736. WCHAR szBuffer[128] = {0};
  737. NAVITEM item = {0};
  738. item.cbSize = sizeof(item);
  739. item.mask = NIMF_TEXTINVARIANT | NIMF_PARAM;
  740. item.pszInvariant = szBuffer;
  741. item.cchInvariantMax = ARRAYSIZE(szBuffer);
  742. item.hItem = hRoot;
  743. while (NULL != item.hItem)
  744. {
  745. if (FALSE != MLNavItem_GetInfo(hLibrary, &item) &&
  746. FALSE != Navigation_CheckInvariantName(item.pszInvariant))
  747. {
  748. ifc_omservice *service = (ifc_omservice*)item.lParam;
  749. if (NULL != service && serviceId == service->GetId())
  750. {
  751. if (NULL != serviceOut)
  752. {
  753. *serviceOut = service;
  754. service->AddRef();
  755. }
  756. return item.hItem;
  757. }
  758. }
  759. item.hItem = (HNAVITEM)SENDMLIPC(hLibrary,
  760. (item.hItem == hRoot) ? ML_IPC_NAVITEM_GETCHILD : ML_IPC_NAVITEM_GETNEXT,
  761. (WPARAM)item.hItem);
  762. }
  763. if (NULL != serviceOut) *serviceOut = NULL;
  764. return NULL;
  765. }
  766. HRESULT Navigation::ShowService(UINT serviceId, LPCWSTR pszUrl)
  767. {
  768. ifc_omservice *service;
  769. HNAVITEM hItem = FindService(serviceId, &service);
  770. if (NULL == hItem) return E_FAIL;
  771. HRESULT hr = SelectItemInt(hItem, serviceId, pszUrl);
  772. service->Release();
  773. return hr;
  774. }
  775. HNAVITEM Navigation::CreateItem(ifc_omservice *service, int altMode)
  776. {
  777. if (NULL == hLibrary || NULL == hRoot) return NULL;
  778. return CreateItemInt(hRoot, service, altMode);
  779. }
  780. HRESULT Navigation::GenerateServiceName(LPWSTR pszBuffer, INT cchBufferMax)
  781. {
  782. if (NULL == pszBuffer) return E_POINTER;
  783. *pszBuffer = L'\0';
  784. if (NULL == hLibrary || NULL == hRoot) return E_UNEXPECTED;
  785. if (FAILED(Plugin_CopyResString(pszBuffer, cchBufferMax, MAKEINTRESOURCE(IDS_USERSERVICE_NAME))))
  786. return E_UNEXPECTED;
  787. INT cchName = lstrlen(pszBuffer);
  788. LPWSTR pszFormat = pszBuffer + cchName;
  789. INT cchFormatMax = cchBufferMax - cchName;
  790. WCHAR szText[512] = {0};
  791. NAVITEM item = {0};
  792. item.cbSize = sizeof(item);
  793. item.mask = NIMF_TEXT;
  794. item.pszText = szText;
  795. item.cchTextMax = ARRAYSIZE(szText);
  796. BOOL fFound = TRUE;
  797. for(INT index = 1; FALSE != fFound; index++)
  798. {
  799. fFound = FALSE;
  800. if (FAILED(StringCchPrintf(pszFormat, cchFormatMax, L" %d", index)))
  801. {
  802. pszFormat = L'\0';
  803. return E_FAIL;
  804. }
  805. item.hItem = MLNavItem_GetChild(hLibrary, hRoot);
  806. while(NULL != item.hItem)
  807. {
  808. if (FALSE != MLNavItem_GetInfo(hLibrary, &item) &&
  809. CSTR_EQUAL == CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, item.pszText, -1, pszBuffer, -1))
  810. {
  811. fFound = TRUE;
  812. break;
  813. }
  814. item.hItem = MLNavItem_GetNext(hLibrary, item.hItem);
  815. }
  816. }
  817. return S_OK;
  818. }
  819. HRESULT Navigation::CreateUserService(HNAVITEM *itemOut)
  820. {
  821. HRESULT hr;
  822. if (NULL != itemOut)
  823. *itemOut = NULL;
  824. if (NULL == hRoot) return E_FAIL;
  825. INT serviceId = 710;
  826. while(NULL != FindService(serviceId, NULL)) serviceId++;
  827. WCHAR szName[256] = {0};
  828. if (FAILED(GenerateServiceName(szName, ARRAYSIZE(szName))))
  829. return E_FAIL;
  830. ifc_omservice *service;
  831. hr = ServiceHelper_Create(serviceId, szName, NULL, L"about:blank", SVCF_SUBSCRIBED | SVCF_PREAUTHORIZED, 2, TRUE, &service);
  832. if (SUCCEEDED(hr))
  833. {
  834. HNAVITEM hItem = CreateItem(service, 1);
  835. if (NULL == hItem)
  836. {
  837. hr = E_FAIL;
  838. }
  839. else
  840. {
  841. if (NULL != itemOut)
  842. *itemOut = hItem;
  843. }
  844. service->Release();
  845. }
  846. return hr;
  847. }
  848. typedef struct __ICONPATCHREC
  849. {
  850. LPCWSTR iconName;
  851. LPCWSTR resourceName;
  852. } ICONPATCHREC;
  853. const static ICONPATCHREC szIconPatch[] =
  854. {
  855. //{ L"11000", MAKEINTRESOURCEW(IDR_ICON_AOL)},
  856. { L"11001", MAKEINTRESOURCEW(IDR_ICON_SHOUTCASTRADIO)},
  857. /*{ L"11002", MAKEINTRESOURCEW(IDR_ICON_SHOUTCASTTV)},
  858. { L"11003", MAKEINTRESOURCEW(IDR_ICON_WINAMPMUSIC)},
  859. { L"11004", MAKEINTRESOURCEW(IDR_ICON_SINGINGFISH)},
  860. { L"11005", MAKEINTRESOURCEW(IDR_ICON_MUSICNOW)},
  861. { L"11006", MAKEINTRESOURCEW(IDR_ICON_AOL_GAMES)},
  862. { L"11007", MAKEINTRESOURCEW(IDR_ICON_IN2TV)},
  863. { L"11008", MAKEINTRESOURCEW(IDR_ICON_WINAMREMOTE)},*/
  864. };
  865. HRESULT Navigation::PatchIconName(LPWSTR pszIcon, UINT cchMaxIconLen, ifc_omservice *service)
  866. {
  867. if (NULL == pszIcon) return E_INVALIDARG;
  868. if (L'\0' == *pszIcon) return S_FALSE;
  869. for(INT i = 0; i < ARRAYSIZE(szIconPatch); i++)
  870. {
  871. if (CSTR_EQUAL == CompareString(CSTR_INVARIANT, NORM_IGNORECASE, szIconPatch[i].iconName, -1, pszIcon, -1))
  872. {
  873. if (IS_INTRESOURCE(szIconPatch[i].resourceName))
  874. {
  875. return Plugin_MakeResourcePath(pszIcon, cchMaxIconLen, RT_RCDATA, szIconPatch[i].resourceName, RESPATH_COMPACT);
  876. }
  877. return StringCchCopy(pszIcon, cchMaxIconLen, szIconPatch[i].resourceName);
  878. }
  879. }
  880. if (FALSE == PathIsURL(pszIcon) && FALSE != PathIsRelative(pszIcon))
  881. {
  882. WCHAR szTemp[2048] = {0};
  883. HRESULT hr = StringCchCopy(szTemp, ARRAYSIZE(szTemp), pszIcon);
  884. if (SUCCEEDED(hr))
  885. {
  886. ServiceHost *serviceHost;
  887. hr = ServiceHost::GetCachedInstance(&serviceHost);
  888. if (SUCCEEDED(hr))
  889. {
  890. WCHAR szBase[MAX_PATH] = {0};
  891. if (SUCCEEDED(serviceHost->GetBasePath(service, szBase, ARRAYSIZE(szBase))))
  892. {
  893. if (L'\0' != szBase[0] && FALSE != PathIsRelative(szBase))
  894. {
  895. LPCWSTR pszUser = (NULL != WASABI_API_APP) ? WASABI_API_APP->path_getUserSettingsPath() : NULL;
  896. if (NULL != pszUser)
  897. {
  898. StringCchCopy(pszIcon, cchMaxIconLen, pszUser);
  899. }
  900. PathAppend(pszIcon, szBase);
  901. }
  902. else
  903. {
  904. StringCchCopy(pszIcon, cchMaxIconLen, szBase);
  905. }
  906. PathAppend(pszIcon, szTemp);
  907. }
  908. serviceHost->Release();
  909. }
  910. }
  911. if (FAILED(hr))
  912. return hr;
  913. }
  914. return S_FALSE;
  915. }
  916. HNAVITEM Navigation::CreateItemInt(HNAVITEM hParent, ifc_omservice *service, int altMode)
  917. {
  918. if (!altMode && (S_OK != ServiceHelper_IsSubscribed(service)))
  919. return NULL;
  920. WCHAR szName[256] = {0}, szInvariant[64] = {0};
  921. if (FAILED(service->GetName(szName, ARRAYSIZE(szName))))
  922. return NULL;
  923. if (L'\0' == szName[0])
  924. WASABI_API_LNGSTRINGW_BUF(IDS_DEFAULT_SERVICENAME, szName, ARRAYSIZE(szName));
  925. if (FAILED(StringCchPrintf(szInvariant, ARRAYSIZE(szInvariant), NAVITEM_PREFIX L"%u", service->GetId())))
  926. return NULL;
  927. NAVINSERTSTRUCT nis = {0};
  928. nis.hInsertAfter = NULL;
  929. nis.hParent = hParent;
  930. INT iIcon = -1;
  931. ifc_mlnavigationhelper *navHelper;
  932. if (NULL != OMUTILITY && SUCCEEDED(OMUTILITY->GetMlNavigationHelper(Plugin_GetLibrary(), &navHelper)))
  933. {
  934. WCHAR szIcon[2048] = {0};
  935. if (FAILED(service->GetIcon(szIcon, ARRAYSIZE(szIcon))) ||
  936. FAILED(PatchIconName(szIcon, ARRAYSIZE(szIcon), service)) ||
  937. FAILED(navHelper->QueryIndex(szIcon, &iIcon, NULL)))
  938. {
  939. iIcon = -1;
  940. }
  941. navHelper->Release();
  942. }
  943. nis.item.cbSize = sizeof(NAVITEM);
  944. nis.item.mask = NIMF_TEXT | NIMF_STYLE | NIMF_TEXTINVARIANT | NIMF_PARAM | NIMF_IMAGE | NIMF_IMAGESEL;
  945. nis.item.id = 0;
  946. nis.item.pszText = szName;
  947. nis.item.pszInvariant = szInvariant;
  948. nis.item.lParam = (LPARAM)service;
  949. nis.item.style = 0;
  950. UINT serviceFlags;
  951. if (FAILED(service->GetFlags(&serviceFlags)))
  952. serviceFlags = 0;
  953. if (0 != (SVCF_SPECIAL & serviceFlags))
  954. {
  955. nis.item.style |= (NIS_HASCHILDREN | NIS_ALLOWCHILDMOVE);
  956. iIcon = -1;
  957. }
  958. nis.item.styleMask = nis.item.style;
  959. nis.item.iImage = iIcon;
  960. nis.item.iSelectedImage = iIcon;
  961. HNAVITEM hItem = MLNavCtrl_InsertItem(hLibrary, &nis);
  962. if (NULL != hItem)
  963. {
  964. ServiceHost *serviceHost;
  965. if (SUCCEEDED(ServiceHost::GetCachedInstance(&serviceHost)))
  966. {
  967. ifc_omserviceeventmngr *eventManager;
  968. if (SUCCEEDED(service->QueryInterface(IFC_OmServiceEventMngr, (void**)&eventManager)))
  969. {
  970. eventManager->RegisterHandler(serviceHost);
  971. eventManager->Release();
  972. }
  973. serviceHost->Release();
  974. }
  975. service->AddRef();
  976. }
  977. return hItem;
  978. }
  979. HRESULT Navigation::SelectItemInt(HNAVITEM hItem, UINT serviceId, LPCWSTR pszUrl)
  980. {
  981. if (NULL == hLibrary) return E_UNEXPECTED;
  982. if (NULL != pszUrl && L'\0' != *pszUrl)
  983. {
  984. HRESULT hr = forceUrl.Set(serviceId, pszUrl);
  985. if (FAILED(hr)) return hr;
  986. }
  987. else
  988. {
  989. forceUrl.Remove(serviceId);
  990. }
  991. if (FALSE == MLNavItem_Select(hLibrary, hItem))
  992. {
  993. forceUrl.Remove(serviceId);
  994. return E_FAIL;
  995. }
  996. return S_OK;
  997. }
  998. HNAVITEM Navigation::GetMessageItem(INT msg, INT_PTR param1)
  999. {
  1000. return (msg < ML_MSG_NAVIGATION_FIRST) ?
  1001. MLNavCtrl_FindItemById(hLibrary, param1) :
  1002. (HNAVITEM)param1;
  1003. }
  1004. HRESULT Navigation::OnCreateView(HNAVITEM hItem, HWND hParent, HWND *hView)
  1005. {
  1006. if (NULL == hView) return E_POINTER;
  1007. *hView = NULL;
  1008. if (NULL == hLibrary) return E_UNEXPECTED;
  1009. if (NULL == hItem || NULL == hParent) return E_INVALIDARG;
  1010. HRESULT hr;
  1011. ifc_omservice *service;
  1012. hr = GetService(hItem, &service);
  1013. if (SUCCEEDED(hr))
  1014. {
  1015. hr = InitializeBrowser();
  1016. if (SUCCEEDED(hr))
  1017. {
  1018. LPWSTR pszUrl;
  1019. if (S_OK != forceUrl.Peek(service->GetId(), &pszUrl))
  1020. pszUrl = NULL;
  1021. hr = OMBROWSERMNGR->CreateView(service, hParent, pszUrl, 0, hView);
  1022. forceUrl.FreeString(pszUrl);
  1023. }
  1024. service->Release();
  1025. }
  1026. return hr;
  1027. }
  1028. HRESULT Navigation::OnContextMenu(HNAVITEM hItem, HWND hHost, POINTS pts)
  1029. {
  1030. if (NULL == hItem || NULL == hHost)
  1031. return E_INVALIDARG;
  1032. HWND hLibrary = Plugin_GetLibrary();
  1033. if (NULL == hLibrary) return E_UNEXPECTED;
  1034. HRESULT hr;
  1035. ifc_omservice *service, *activeService;
  1036. hr = GetService(hItem, &service);
  1037. if (FAILED(hr)) return hr;
  1038. POINT pt;
  1039. POINTSTOPOINT(pt, pts);
  1040. if (-1 == pt.x || -1 == pt.y)
  1041. {
  1042. NAVITEMGETRECT itemRect;
  1043. itemRect.fItem = FALSE;
  1044. itemRect.hItem = hItem;
  1045. if (MLNavItem_GetRect(hLibrary, &itemRect))
  1046. {
  1047. MapWindowPoints(hHost, HWND_DESKTOP, (POINT*)&itemRect.rc, 2);
  1048. pt.x = itemRect.rc.left + 2;
  1049. pt.y = itemRect.rc.top + 2;
  1050. }
  1051. }
  1052. HWND activeView = GetActiveView(&activeService);
  1053. if (NULL == activeView) activeService = NULL;
  1054. INT menuKind = (hItem == hRoot) ? OMMENU_GALERYCONTEXT : OMMENU_SERVICECONTEXT;
  1055. UINT menuFlags = MCF_VIEW;
  1056. if (NULL != activeService && activeService->GetId() == service->GetId())
  1057. menuFlags |= MCF_VIEWACTIVE;
  1058. UINT rating;
  1059. if (OMMENU_SERVICECONTEXT == menuKind && SUCCEEDED(service->GetRating(&rating)))
  1060. menuFlags |= RATINGTOMCF(rating);
  1061. HMENU hMenu = Menu_GetMenu(menuKind, menuFlags);
  1062. if (NULL != hMenu)
  1063. {
  1064. INT commandId = DoTrackPopup(hMenu, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_NONOTIFY | TPM_RETURNCMD,
  1065. pt.x, pt.y, hHost, NULL);
  1066. Menu_ReleaseMenu(hMenu, menuKind);
  1067. if (0 != commandId && FALSE != Command_ProcessService(activeView, service, commandId, NULL))
  1068. commandId = 0;
  1069. if (0 != commandId && NULL != activeView && FALSE != Command_ProcessView(activeView, commandId, NULL))
  1070. commandId = 0;
  1071. if (0 != commandId && FALSE != Command_ProcessGeneral(commandId, NULL))
  1072. commandId = 0;
  1073. }
  1074. if (NULL != activeService)
  1075. activeService->Release();
  1076. service->Release();
  1077. return hr;
  1078. }
  1079. HRESULT Navigation::OnEndTitleEdit(HNAVITEM hItem, LPCWSTR pszNewTitle)
  1080. {
  1081. if (NULL == hItem) return E_INVALIDARG;
  1082. if (NULL == hLibrary) return E_UNEXPECTED;
  1083. HRESULT hr;
  1084. ifc_omservice *service;
  1085. hr = GetService(hItem, &service);
  1086. if (SUCCEEDED(hr))
  1087. {
  1088. if (NULL != pszNewTitle)
  1089. {
  1090. ifc_omserviceeditor *editor;
  1091. hr = service->QueryInterface(IFC_OmServiceEditor, (void**)&editor);
  1092. if (SUCCEEDED(hr))
  1093. {
  1094. hr = editor->SetName(pszNewTitle, FALSE);
  1095. editor->Release();
  1096. }
  1097. }
  1098. if (SUCCEEDED(hr))
  1099. ServiceHelper_Save(service);
  1100. service->Release();
  1101. }
  1102. return hr;
  1103. }
  1104. HRESULT Navigation::OnDeleteItem(HNAVITEM hItem)
  1105. {
  1106. if (NULL == hItem) return E_INVALIDARG;
  1107. if (NULL == hLibrary) return E_UNEXPECTED;
  1108. WCHAR szBuffer[2048] = {0};
  1109. NAVITEM itemInfo = {0};
  1110. itemInfo.cbSize = sizeof(itemInfo);
  1111. itemInfo.hItem = hItem;
  1112. itemInfo.pszInvariant = szBuffer;
  1113. itemInfo.cchInvariantMax = ARRAYSIZE(szBuffer);
  1114. itemInfo.mask = NIMF_PARAM | NIMF_TEXTINVARIANT | NIMF_IMAGE;
  1115. if (FALSE == MLNavItem_GetInfo(hLibrary, &itemInfo))
  1116. return E_FAIL;
  1117. if (FALSE == Navigation_CheckInvariantName(szBuffer))
  1118. return E_NAVITEM_UNKNOWN;
  1119. ifc_omservice *service = (ifc_omservice*)itemInfo.lParam;
  1120. if (NULL != service)
  1121. {
  1122. if (SUCCEEDED(service->GetIcon(szBuffer, ARRAYSIZE(szBuffer))))
  1123. {
  1124. ifc_mlnavigationhelper *navHelper;
  1125. if (SUCCEEDED(OMUTILITY->GetMlNavigationHelper(Plugin_GetLibrary(), &navHelper)))
  1126. {
  1127. navHelper->ReleaseIndex(szBuffer);
  1128. navHelper->Release();
  1129. }
  1130. }
  1131. ifc_ombrowserwndmngr *windowManager;
  1132. if (NULL != OMBROWSERMNGR && SUCCEEDED(OMBROWSERMNGR->QueryInterface(IFC_OmBrowserWindowManager, (void**)&windowManager)))
  1133. {
  1134. UINT serviceId = service->GetId();
  1135. ifc_ombrowserwndenum *windowEnum;
  1136. if (SUCCEEDED(windowManager->Enumerate(NULL, &serviceId, &windowEnum)))
  1137. {
  1138. HWND hwnd;
  1139. while (S_OK == windowEnum->Next(1, &hwnd, NULL))
  1140. {
  1141. DestroyWindow(hwnd);
  1142. }
  1143. windowEnum->Release();
  1144. }
  1145. windowManager->Release();
  1146. }
  1147. ServiceHost *serviceHost;
  1148. if (SUCCEEDED(ServiceHost::GetCachedInstance(&serviceHost)))
  1149. {
  1150. ifc_omserviceeventmngr *eventManager;
  1151. if (SUCCEEDED(service->QueryInterface(IFC_OmServiceEventMngr, (void**)&eventManager)))
  1152. {
  1153. eventManager->UnregisterHandler(serviceHost);
  1154. eventManager->Release();
  1155. }
  1156. serviceHost->Release();
  1157. }
  1158. itemInfo.mask = NIMF_PARAM;
  1159. itemInfo.lParam = 0L;
  1160. MLNavItem_SetInfo(hLibrary, &itemInfo);
  1161. service->Release();
  1162. }
  1163. return S_OK;
  1164. }
  1165. HRESULT Navigation::OnKeyDown(HNAVITEM hItem, NMTVKEYDOWN *pnmkd)
  1166. {
  1167. if (NULL == hItem) return E_INVALIDARG;
  1168. if (NULL == hLibrary) return E_UNEXPECTED;
  1169. ifc_omservice *service;
  1170. HRESULT hr = GetService(hItem, &service);
  1171. if (SUCCEEDED(hr))
  1172. {
  1173. switch(pnmkd->wVKey)
  1174. {
  1175. case VK_DELETE:
  1176. {
  1177. BOOL fSuccess;
  1178. ifc_omservice *activeService;
  1179. HWND activeView = GetActiveView(&activeService);
  1180. if (IsWindow(activeView))
  1181. {
  1182. Command_ProcessService(activeView, service, ID_SERVICE_UNSUBSCRIBE, &fSuccess);
  1183. }
  1184. }
  1185. break;
  1186. }
  1187. service->Release();
  1188. }
  1189. return hr;
  1190. }
  1191. HRESULT Navigation::OnControlDestroy()
  1192. {
  1193. SaveOrder();
  1194. return S_OK;
  1195. }
  1196. #define CBCLASS Navigation
  1197. START_DISPATCH;
  1198. CB(ADDREF, AddRef)
  1199. CB(RELEASE, Release)
  1200. CB(QUERYINTERFACE, QueryInterface)
  1201. VCB(API_IMAGECHANGED, ImageChanged)
  1202. END_DISPATCH;
  1203. #undef CBCLASS