navigation.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
  1. #include <strsafe.h>
  2. #include "main.h"
  3. #include "./navigation.h"
  4. #include "./util.h"
  5. #include "./resource.h"
  6. #include "api__ml_wire.h"
  7. #include "./service.h"
  8. #include "./subscriptionView.h"
  9. #include "./downloadsDialog.h"
  10. #include "../omBrowser/browserView.h"
  11. #include "../winamp/wa_ipc.h"
  12. #include "..\..\General\gen_ml/ml_ipc_0313.h"
  13. #include "./Defaults.h"
  14. #define NAVITEM_PREFIX L"podcast_svc_"
  15. #define E_NAVITEM_UNKNOWN E_NOINTERFACE
  16. static Nullsoft::Utility::LockGuard navigationLock;
  17. static INT Navigation_RegisterIcon( HWND hLibrary, INT iconIndex, LPCWSTR pszImage )
  18. {
  19. HMLIMGLST hmlilNavigation = MLNavCtrl_GetImageList( hLibrary );
  20. if ( hmlilNavigation == NULL )
  21. return -1;
  22. MLIMAGESOURCE mlis;
  23. ZeroMemory( &mlis, sizeof( MLIMAGESOURCE ) );
  24. mlis.cbSize = sizeof( MLIMAGESOURCE );
  25. mlis.hInst = NULL;
  26. mlis.bpp = 24;
  27. mlis.lpszName = pszImage;
  28. mlis.type = SRC_TYPE_PNG;
  29. mlis.flags = ISF_FORCE_BPP | ISF_PREMULTIPLY | ISF_LOADFROMFILE;
  30. MLIMAGELISTITEM item;
  31. ZeroMemory( &item, sizeof( MLIMAGELISTITEM ) );
  32. item.cbSize = sizeof( MLIMAGELISTITEM );
  33. item.hmlil = hmlilNavigation;
  34. item.filterUID = MLIF_FILTER3_UID;
  35. item.pmlImgSource = &mlis;
  36. if (iconIndex >= 0)
  37. {
  38. INT count = MLImageList_GetImageCount( hLibrary, item.hmlil );
  39. if (iconIndex < count)
  40. {
  41. item.mlilIndex = iconIndex;
  42. return (FALSE != MLImageList_Replace(hLibrary, &item)) ? iconIndex : -1;
  43. }
  44. }
  45. return MLImageList_Add( hLibrary, &item );
  46. }
  47. static HNAVITEM Navigation_CreateItem( HWND hLibrary, HNAVITEM hParent, OmService *service )
  48. {
  49. if ( hLibrary == NULL || service == NULL )
  50. return NULL;
  51. WCHAR szName[ 256 ] = { 0 }, szInvariant[ 64 ] = { 0 };
  52. if ( FAILED( service->GetName( szName, ARRAYSIZE( szName ) ) ) )
  53. return NULL;
  54. if ( FAILED( StringCchPrintf( szInvariant, ARRAYSIZE( szInvariant ), NAVITEM_PREFIX L"%u", service->GetId() ) ) )
  55. return NULL;
  56. NAVINSERTSTRUCT nis = { 0 };
  57. nis.hInsertAfter = NULL;
  58. nis.hParent = hParent;
  59. WCHAR szIcon[ 512 ] = { 0 };
  60. INT iIcon = ( SUCCEEDED( service->GetIcon( szIcon, ARRAYSIZE( szIcon ) ) ) ) ? Navigation_RegisterIcon( hLibrary, -1, szIcon ) : -1;
  61. nis.item.cbSize = sizeof( NAVITEM );
  62. nis.item.mask = NIMF_TEXT | NIMF_STYLE | NIMF_TEXTINVARIANT | NIMF_PARAM | NIMF_IMAGE | NIMF_IMAGESEL;
  63. nis.item.id = 0;
  64. nis.item.pszText = szName;
  65. nis.item.pszInvariant = szInvariant;
  66. nis.item.lParam = (LPARAM)service;
  67. nis.item.style = 0;
  68. UINT serviceFlags = service->GetFlags();
  69. if ( ( OmService::flagRoot & serviceFlags ) != 0 )
  70. nis.item.style |= ( NIS_HASCHILDREN | NIS_DEFAULTIMAGE );
  71. nis.item.styleMask = nis.item.style;
  72. nis.item.iImage = iIcon;
  73. nis.item.iSelectedImage = iIcon;
  74. HNAVITEM hItem = MLNavCtrl_InsertItem( hLibrary, &nis );
  75. if ( hItem != NULL )
  76. service->AddRef();
  77. return hItem;
  78. }
  79. static HNAVITEM Navigation_GetMessageItem( INT msg, INT_PTR param1 )
  80. {
  81. HWND hLibrary = plugin.hwndLibraryParent;
  82. HNAVITEM hItem = ( msg < ML_MSG_NAVIGATION_FIRST ) ? MLNavCtrl_FindItemById( hLibrary, param1 ) : (HNAVITEM)param1;
  83. return hItem;
  84. }
  85. static BOOL Navigation_CheckInvariantName( LPCWSTR pszInvarian )
  86. {
  87. INT cchInvariant = ( NULL != pszInvarian ) ? lstrlen( pszInvarian ) : 0;
  88. INT cchPrefix = ARRAYSIZE( NAVITEM_PREFIX ) - 1;
  89. return ( cchInvariant > cchPrefix &&
  90. CompareString( CSTR_INVARIANT, 0, NAVITEM_PREFIX, cchPrefix, pszInvarian, cchPrefix ) == CSTR_EQUAL );
  91. }
  92. static HRESULT Navigation_GetServiceInt( HWND hLibrary, HNAVITEM hItem, OmService **service )
  93. {
  94. WCHAR szBuffer[ 64 ] = { 0 };
  95. if ( service == NULL )
  96. return E_POINTER;
  97. *service = NULL;
  98. if ( NULL == hLibrary || NULL == hItem )
  99. return E_INVALIDARG;
  100. NAVITEM itemInfo = {0};
  101. itemInfo.cbSize = sizeof( NAVITEM );
  102. itemInfo.hItem = hItem;
  103. itemInfo.pszInvariant = szBuffer;
  104. itemInfo.cchInvariantMax = ARRAYSIZE( szBuffer );
  105. itemInfo.mask = NIMF_PARAM | NIMF_TEXTINVARIANT;
  106. if ( FALSE == MLNavItem_GetInfo( hLibrary, &itemInfo ) )
  107. return E_FAIL;
  108. if ( FALSE == Navigation_CheckInvariantName( szBuffer ) )
  109. return E_NAVITEM_UNKNOWN;
  110. *service = (OmService *)itemInfo.lParam;
  111. (*service)->AddRef();
  112. return S_OK;
  113. }
  114. HRESULT Navigation_GetService( HNAVITEM hItem, OmService **service )
  115. {
  116. return Navigation_GetServiceInt( plugin.hwndLibraryParent, hItem, service );
  117. }
  118. static HRESULT Navigation_CreateView( HNAVITEM hItem, HWND hParent, HWND *hView )
  119. {
  120. if ( NULL == hView )
  121. return E_POINTER;
  122. *hView = NULL;
  123. if ( hItem == NULL || hParent == NULL )
  124. return E_INVALIDARG;
  125. HRESULT hr;
  126. OmService *service;
  127. hr = Navigation_GetServiceInt( plugin.hwndLibraryParent, hItem, &service );
  128. if ( SUCCEEDED( hr ) )
  129. {
  130. if ( service->GetId() == SERVICE_PODCAST )
  131. service->SetUrl( serviceUrl[ 0 ] ? serviceUrl : L"https://client.winamp.com/podcasts" );
  132. hr = service->CreateView( hParent, hView );
  133. service->Release();
  134. }
  135. return hr;
  136. }
  137. static void Navigation_OnDestroy()
  138. {
  139. if ( OMBROWSERMNGR != NULL )
  140. OMBROWSERMNGR->Finish();
  141. }
  142. HNAVITEM Navigation_FindService( UINT serviceId, HNAVITEM hStart, OmService **serviceOut )
  143. {
  144. HWND hLibrary = plugin.hwndLibraryParent;
  145. INT cchPrefix = ARRAYSIZE( NAVITEM_PREFIX ) - 1;
  146. WCHAR szBuffer[256] = {0};
  147. NAVITEM itemInfo = {0};
  148. itemInfo.cbSize = sizeof( itemInfo );
  149. itemInfo.mask = NIMF_TEXTINVARIANT | NIMF_PARAM;
  150. itemInfo.cchInvariantMax = ARRAYSIZE( szBuffer );
  151. itemInfo.pszInvariant = szBuffer;
  152. if ( hStart == NULL )
  153. hStart = MLNavCtrl_GetFirst( hLibrary );
  154. itemInfo.hItem = hStart;
  155. while ( itemInfo.hItem != NULL )
  156. {
  157. if ( FALSE != MLNavItem_GetInfo( hLibrary, &itemInfo ) &&
  158. CSTR_EQUAL == CompareString( CSTR_INVARIANT, NORM_IGNORECASE, itemInfo.pszInvariant, cchPrefix,
  159. NAVITEM_PREFIX, cchPrefix ) )
  160. {
  161. OmService *service = (OmService *)itemInfo.lParam;
  162. if ( service != NULL && service->GetId() == serviceId )
  163. {
  164. if ( serviceOut != NULL )
  165. {
  166. *serviceOut = service;
  167. service->AddRef();
  168. }
  169. return itemInfo.hItem;
  170. }
  171. }
  172. itemInfo.hItem = MLNavItem_GetNext( hLibrary, itemInfo.hItem );
  173. }
  174. if ( serviceOut != NULL )
  175. *serviceOut = NULL;
  176. return NULL;
  177. }
  178. int downloadsViewLoaded = -1;
  179. static int Navigation_CheckDownloadsView()
  180. {
  181. if ( downloadsViewLoaded == -1 )
  182. {
  183. pluginMessage p = { ML_MSG_DOWNLOADS_VIEW_LOADED, 0, 0, 0 };
  184. downloadsViewLoaded = SENDMLIPC( plugin.hwndLibraryParent, ML_IPC_SEND_PLUGIN_MESSAGE, (WPARAM)&p );
  185. }
  186. return downloadsViewLoaded;
  187. }
  188. HRESULT Navigation_ShowService( UINT serviceId, INT showMode )
  189. {
  190. if ( serviceId == SERVICE_DOWNLOADS && Navigation_CheckDownloadsView() )
  191. return S_OK;
  192. Nullsoft::Utility::AutoLock lock3( navigationLock );
  193. HNAVITEM hRoot = Navigation_FindService( SERVICE_PODCAST, NULL, NULL );
  194. if( hRoot == NULL )
  195. return E_UNEXPECTED;
  196. switch ( serviceId )
  197. {
  198. case SERVICE_SUBSCRIPTION:
  199. if ( SHOWMODE_AUTO == showMode )
  200. return E_INVALIDARG;
  201. break;
  202. case SERVICE_DOWNLOADS:
  203. if ( SHOWMODE_AUTO == showMode )
  204. {
  205. Nullsoft::Utility::AutoLock lock1( downloadedFiles.downloadedLock );
  206. Nullsoft::Utility::AutoLock lock2( downloadStatus.statusLock );
  207. showMode = ( 0 != downloadedFiles.downloadList.size() || 0 != downloadStatus.downloads.size() ) ? SHOWMODE_SHOW : SHOWMODE_HIDE;
  208. }
  209. break;
  210. default:
  211. return E_INVALIDARG;
  212. }
  213. if ( showMode != SHOWMODE_HIDE && showMode != SHOWMODE_SHOW )
  214. return E_INVALIDARG;
  215. HWND hLibrary = plugin.hwndLibraryParent;
  216. MLNavCtrl_BeginUpdate( hLibrary, NUF_LOCK_TOP );
  217. OmService *service;
  218. HNAVITEM hItem = MLNavItem_GetChild( hLibrary, hRoot );
  219. hItem = Navigation_FindService( serviceId, hItem, &service );
  220. HRESULT hr = S_OK;
  221. if ( showMode == SHOWMODE_HIDE )
  222. {
  223. if ( hItem == NULL )
  224. hr = S_FALSE;
  225. else if ( MLNavCtrl_DeleteItem( hLibrary, hItem ) == FALSE )
  226. hr = E_FAIL;
  227. }
  228. else
  229. {
  230. if ( hItem != NULL )
  231. hr = S_FALSE;
  232. else
  233. {
  234. switch ( serviceId )
  235. {
  236. case SERVICE_SUBSCRIPTION:
  237. hr = OmService::CreateLocal( SERVICE_SUBSCRIPTION, MAKEINTRESOURCE( IDS_SUBSCRIPTIONS ), MAKEINTRESOURCE( IDR_SUBSCRIPTION_ICON ), SubscriptionView_Create, &service );
  238. break;
  239. case SERVICE_DOWNLOADS:
  240. hr = OmService::CreateLocal( SERVICE_DOWNLOADS, MAKEINTRESOURCE( IDS_DOWNLOADS ), MAKEINTRESOURCE( IDR_DOWNLOAD_ICON ), DownloadDialog_Create, &service );
  241. break;
  242. default:
  243. hr = E_UNEXPECTED;
  244. break;
  245. }
  246. if ( SUCCEEDED( hr ) )
  247. {
  248. if ( Navigation_CreateItem( hLibrary, hRoot, service ) == NULL )
  249. hr = E_FAIL;
  250. }
  251. }
  252. }
  253. if ( service != NULL )
  254. service->Release();
  255. MLNavCtrl_EndUpdate( hLibrary );
  256. return hr;
  257. }
  258. BOOL Navigation_Initialize( void )
  259. {
  260. HNAVITEM hParent = NULL;
  261. OmService *service = NULL;
  262. HWND hLibrary = plugin.hwndLibraryParent;
  263. MLNavCtrl_BeginUpdate( hLibrary, NUF_LOCK_TOP );
  264. if ( SUCCEEDED( OmService::CreateRemote( SERVICE_PODCAST, MAKEINTRESOURCE( IDS_PODCAST_DIRECTORY ),
  265. MAKEINTRESOURCE( IDR_DISCOVER_ICON ),
  266. ( serviceUrl[ 0 ] ? serviceUrl : L"https://client.winamp.com/podcasts" ), &service ) ) )
  267. {
  268. service->SetFlags( OmService::flagRoot, OmService::flagRoot );
  269. hParent = Navigation_CreateItem( hLibrary, hParent, service );
  270. service->Release();
  271. }
  272. if ( hParent != NULL )
  273. {
  274. Navigation_ShowService( SERVICE_SUBSCRIPTION, SHOWMODE_SHOW );
  275. //Navigation_ShowService(SERVICE_DOWNLOADS, SHOWMODE_AUTO);
  276. }
  277. MLNavCtrl_EndUpdate( hLibrary );
  278. return TRUE;
  279. }
  280. static void Navigation_OnDeleteItem( HNAVITEM hItem )
  281. {
  282. if ( hItem == NULL )
  283. return;
  284. HWND hLibrary = plugin.hwndLibraryParent;
  285. if ( hLibrary == NULL )
  286. return;
  287. WCHAR szBuffer[64] = {0};
  288. NAVITEM itemInfo = {0};
  289. itemInfo.cbSize = sizeof( itemInfo );
  290. itemInfo.hItem = hItem;
  291. itemInfo.pszInvariant = szBuffer;
  292. itemInfo.cchInvariantMax = ARRAYSIZE( szBuffer );
  293. itemInfo.mask = NIMF_PARAM | NIMF_TEXTINVARIANT | NIMF_IMAGE;
  294. if ( MLNavItem_GetInfo( hLibrary, &itemInfo ) != FALSE && Navigation_CheckInvariantName( szBuffer ) != FALSE )
  295. {
  296. OmService *service = (OmService *)itemInfo.lParam;
  297. itemInfo.mask = NIMF_PARAM;
  298. itemInfo.lParam = 0L;
  299. MLNavItem_SetInfo( hLibrary, &itemInfo );
  300. service->Release();
  301. }
  302. }
  303. BOOL Navigation_ProcessMessage( INT msg, INT_PTR param1, INT_PTR param2, INT_PTR param3, INT_PTR *result )
  304. {
  305. if (msg < ML_MSG_TREE_BEGIN || msg > ML_MSG_TREE_END)
  306. return FALSE;
  307. switch ( msg )
  308. {
  309. case ML_MSG_TREE_ONCREATEVIEW:
  310. {
  311. HWND hView = NULL;
  312. HRESULT hr = Navigation_CreateView( Navigation_GetMessageItem( msg, param1 ), (HWND)param2, &hView );
  313. *result = ( SUCCEEDED( hr ) ) ? (INT_PTR)hView : NULL;
  314. return TRUE;
  315. }
  316. case ML_MSG_NAVIGATION_ONDESTROY:
  317. Navigation_OnDestroy();
  318. return TRUE;
  319. case ML_MSG_NAVIGATION_ONDELETE:
  320. Navigation_OnDeleteItem( Navigation_GetMessageItem( msg, param1 ) );
  321. return TRUE;
  322. }
  323. return FALSE;
  324. }