#include #include "main.h" #include "./navigation.h" #include "./util.h" #include "./resource.h" #include "api__ml_wire.h" #include "./service.h" #include "./subscriptionView.h" #include "./downloadsDialog.h" #include "../omBrowser/browserView.h" #include "../winamp/wa_ipc.h" #include "..\..\General\gen_ml/ml_ipc_0313.h" #include "./Defaults.h" #define NAVITEM_PREFIX L"podcast_svc_" #define E_NAVITEM_UNKNOWN E_NOINTERFACE static Nullsoft::Utility::LockGuard navigationLock; static INT Navigation_RegisterIcon( HWND hLibrary, INT iconIndex, LPCWSTR pszImage ) { HMLIMGLST hmlilNavigation = MLNavCtrl_GetImageList( hLibrary ); if ( hmlilNavigation == NULL ) return -1; MLIMAGESOURCE mlis; ZeroMemory( &mlis, sizeof( MLIMAGESOURCE ) ); mlis.cbSize = sizeof( MLIMAGESOURCE ); mlis.hInst = NULL; mlis.bpp = 24; mlis.lpszName = pszImage; mlis.type = SRC_TYPE_PNG; mlis.flags = ISF_FORCE_BPP | ISF_PREMULTIPLY | ISF_LOADFROMFILE; MLIMAGELISTITEM item; ZeroMemory( &item, sizeof( MLIMAGELISTITEM ) ); item.cbSize = sizeof( MLIMAGELISTITEM ); item.hmlil = hmlilNavigation; item.filterUID = MLIF_FILTER3_UID; item.pmlImgSource = &mlis; if (iconIndex >= 0) { INT count = MLImageList_GetImageCount( hLibrary, item.hmlil ); if (iconIndex < count) { item.mlilIndex = iconIndex; return (FALSE != MLImageList_Replace(hLibrary, &item)) ? iconIndex : -1; } } return MLImageList_Add( hLibrary, &item ); } static HNAVITEM Navigation_CreateItem( HWND hLibrary, HNAVITEM hParent, OmService *service ) { if ( hLibrary == NULL || service == NULL ) return NULL; WCHAR szName[ 256 ] = { 0 }, szInvariant[ 64 ] = { 0 }; if ( FAILED( service->GetName( szName, ARRAYSIZE( szName ) ) ) ) return NULL; if ( FAILED( StringCchPrintf( szInvariant, ARRAYSIZE( szInvariant ), NAVITEM_PREFIX L"%u", service->GetId() ) ) ) return NULL; NAVINSERTSTRUCT nis = { 0 }; nis.hInsertAfter = NULL; nis.hParent = hParent; WCHAR szIcon[ 512 ] = { 0 }; INT iIcon = ( SUCCEEDED( service->GetIcon( szIcon, ARRAYSIZE( szIcon ) ) ) ) ? Navigation_RegisterIcon( hLibrary, -1, szIcon ) : -1; nis.item.cbSize = sizeof( NAVITEM ); nis.item.mask = NIMF_TEXT | NIMF_STYLE | NIMF_TEXTINVARIANT | NIMF_PARAM | NIMF_IMAGE | NIMF_IMAGESEL; nis.item.id = 0; nis.item.pszText = szName; nis.item.pszInvariant = szInvariant; nis.item.lParam = (LPARAM)service; nis.item.style = 0; UINT serviceFlags = service->GetFlags(); if ( ( OmService::flagRoot & serviceFlags ) != 0 ) nis.item.style |= ( NIS_HASCHILDREN | NIS_DEFAULTIMAGE ); nis.item.styleMask = nis.item.style; nis.item.iImage = iIcon; nis.item.iSelectedImage = iIcon; HNAVITEM hItem = MLNavCtrl_InsertItem( hLibrary, &nis ); if ( hItem != NULL ) service->AddRef(); return hItem; } static HNAVITEM Navigation_GetMessageItem( INT msg, INT_PTR param1 ) { HWND hLibrary = plugin.hwndLibraryParent; HNAVITEM hItem = ( msg < ML_MSG_NAVIGATION_FIRST ) ? MLNavCtrl_FindItemById( hLibrary, param1 ) : (HNAVITEM)param1; return hItem; } static BOOL Navigation_CheckInvariantName( LPCWSTR pszInvarian ) { INT cchInvariant = ( NULL != pszInvarian ) ? lstrlen( pszInvarian ) : 0; INT cchPrefix = ARRAYSIZE( NAVITEM_PREFIX ) - 1; return ( cchInvariant > cchPrefix && CompareString( CSTR_INVARIANT, 0, NAVITEM_PREFIX, cchPrefix, pszInvarian, cchPrefix ) == CSTR_EQUAL ); } static HRESULT Navigation_GetServiceInt( HWND hLibrary, HNAVITEM hItem, OmService **service ) { WCHAR szBuffer[ 64 ] = { 0 }; if ( service == NULL ) return E_POINTER; *service = NULL; if ( NULL == hLibrary || NULL == hItem ) return E_INVALIDARG; NAVITEM itemInfo = {0}; itemInfo.cbSize = sizeof( NAVITEM ); itemInfo.hItem = hItem; itemInfo.pszInvariant = szBuffer; itemInfo.cchInvariantMax = ARRAYSIZE( szBuffer ); itemInfo.mask = NIMF_PARAM | NIMF_TEXTINVARIANT; if ( FALSE == MLNavItem_GetInfo( hLibrary, &itemInfo ) ) return E_FAIL; if ( FALSE == Navigation_CheckInvariantName( szBuffer ) ) return E_NAVITEM_UNKNOWN; *service = (OmService *)itemInfo.lParam; (*service)->AddRef(); return S_OK; } HRESULT Navigation_GetService( HNAVITEM hItem, OmService **service ) { return Navigation_GetServiceInt( plugin.hwndLibraryParent, hItem, service ); } static HRESULT Navigation_CreateView( HNAVITEM hItem, HWND hParent, HWND *hView ) { if ( NULL == hView ) return E_POINTER; *hView = NULL; if ( hItem == NULL || hParent == NULL ) return E_INVALIDARG; HRESULT hr; OmService *service; hr = Navigation_GetServiceInt( plugin.hwndLibraryParent, hItem, &service ); if ( SUCCEEDED( hr ) ) { if ( service->GetId() == SERVICE_PODCAST ) service->SetUrl( serviceUrl[ 0 ] ? serviceUrl : L"https://client.winamp.com/podcasts" ); hr = service->CreateView( hParent, hView ); service->Release(); } return hr; } static void Navigation_OnDestroy() { if ( OMBROWSERMNGR != NULL ) OMBROWSERMNGR->Finish(); } HNAVITEM Navigation_FindService( UINT serviceId, HNAVITEM hStart, OmService **serviceOut ) { HWND hLibrary = plugin.hwndLibraryParent; INT cchPrefix = ARRAYSIZE( NAVITEM_PREFIX ) - 1; WCHAR szBuffer[256] = {0}; NAVITEM itemInfo = {0}; itemInfo.cbSize = sizeof( itemInfo ); itemInfo.mask = NIMF_TEXTINVARIANT | NIMF_PARAM; itemInfo.cchInvariantMax = ARRAYSIZE( szBuffer ); itemInfo.pszInvariant = szBuffer; if ( hStart == NULL ) hStart = MLNavCtrl_GetFirst( hLibrary ); itemInfo.hItem = hStart; while ( itemInfo.hItem != NULL ) { if ( FALSE != MLNavItem_GetInfo( hLibrary, &itemInfo ) && CSTR_EQUAL == CompareString( CSTR_INVARIANT, NORM_IGNORECASE, itemInfo.pszInvariant, cchPrefix, NAVITEM_PREFIX, cchPrefix ) ) { OmService *service = (OmService *)itemInfo.lParam; if ( service != NULL && service->GetId() == serviceId ) { if ( serviceOut != NULL ) { *serviceOut = service; service->AddRef(); } return itemInfo.hItem; } } itemInfo.hItem = MLNavItem_GetNext( hLibrary, itemInfo.hItem ); } if ( serviceOut != NULL ) *serviceOut = NULL; return NULL; } int downloadsViewLoaded = -1; static int Navigation_CheckDownloadsView() { if ( downloadsViewLoaded == -1 ) { pluginMessage p = { ML_MSG_DOWNLOADS_VIEW_LOADED, 0, 0, 0 }; downloadsViewLoaded = SENDMLIPC( plugin.hwndLibraryParent, ML_IPC_SEND_PLUGIN_MESSAGE, (WPARAM)&p ); } return downloadsViewLoaded; } HRESULT Navigation_ShowService( UINT serviceId, INT showMode ) { if ( serviceId == SERVICE_DOWNLOADS && Navigation_CheckDownloadsView() ) return S_OK; Nullsoft::Utility::AutoLock lock3( navigationLock ); HNAVITEM hRoot = Navigation_FindService( SERVICE_PODCAST, NULL, NULL ); if( hRoot == NULL ) return E_UNEXPECTED; switch ( serviceId ) { case SERVICE_SUBSCRIPTION: if ( SHOWMODE_AUTO == showMode ) return E_INVALIDARG; break; case SERVICE_DOWNLOADS: if ( SHOWMODE_AUTO == showMode ) { Nullsoft::Utility::AutoLock lock1( downloadedFiles.downloadedLock ); Nullsoft::Utility::AutoLock lock2( downloadStatus.statusLock ); showMode = ( 0 != downloadedFiles.downloadList.size() || 0 != downloadStatus.downloads.size() ) ? SHOWMODE_SHOW : SHOWMODE_HIDE; } break; default: return E_INVALIDARG; } if ( showMode != SHOWMODE_HIDE && showMode != SHOWMODE_SHOW ) return E_INVALIDARG; HWND hLibrary = plugin.hwndLibraryParent; MLNavCtrl_BeginUpdate( hLibrary, NUF_LOCK_TOP ); OmService *service; HNAVITEM hItem = MLNavItem_GetChild( hLibrary, hRoot ); hItem = Navigation_FindService( serviceId, hItem, &service ); HRESULT hr = S_OK; if ( showMode == SHOWMODE_HIDE ) { if ( hItem == NULL ) hr = S_FALSE; else if ( MLNavCtrl_DeleteItem( hLibrary, hItem ) == FALSE ) hr = E_FAIL; } else { if ( hItem != NULL ) hr = S_FALSE; else { switch ( serviceId ) { case SERVICE_SUBSCRIPTION: hr = OmService::CreateLocal( SERVICE_SUBSCRIPTION, MAKEINTRESOURCE( IDS_SUBSCRIPTIONS ), MAKEINTRESOURCE( IDR_SUBSCRIPTION_ICON ), SubscriptionView_Create, &service ); break; case SERVICE_DOWNLOADS: hr = OmService::CreateLocal( SERVICE_DOWNLOADS, MAKEINTRESOURCE( IDS_DOWNLOADS ), MAKEINTRESOURCE( IDR_DOWNLOAD_ICON ), DownloadDialog_Create, &service ); break; default: hr = E_UNEXPECTED; break; } if ( SUCCEEDED( hr ) ) { if ( Navigation_CreateItem( hLibrary, hRoot, service ) == NULL ) hr = E_FAIL; } } } if ( service != NULL ) service->Release(); MLNavCtrl_EndUpdate( hLibrary ); return hr; } BOOL Navigation_Initialize( void ) { HNAVITEM hParent = NULL; OmService *service = NULL; HWND hLibrary = plugin.hwndLibraryParent; MLNavCtrl_BeginUpdate( hLibrary, NUF_LOCK_TOP ); if ( SUCCEEDED( OmService::CreateRemote( SERVICE_PODCAST, MAKEINTRESOURCE( IDS_PODCAST_DIRECTORY ), MAKEINTRESOURCE( IDR_DISCOVER_ICON ), ( serviceUrl[ 0 ] ? serviceUrl : L"https://client.winamp.com/podcasts" ), &service ) ) ) { service->SetFlags( OmService::flagRoot, OmService::flagRoot ); hParent = Navigation_CreateItem( hLibrary, hParent, service ); service->Release(); } if ( hParent != NULL ) { Navigation_ShowService( SERVICE_SUBSCRIPTION, SHOWMODE_SHOW ); //Navigation_ShowService(SERVICE_DOWNLOADS, SHOWMODE_AUTO); } MLNavCtrl_EndUpdate( hLibrary ); return TRUE; } static void Navigation_OnDeleteItem( HNAVITEM hItem ) { if ( hItem == NULL ) return; HWND hLibrary = plugin.hwndLibraryParent; if ( hLibrary == NULL ) return; WCHAR szBuffer[64] = {0}; NAVITEM itemInfo = {0}; itemInfo.cbSize = sizeof( itemInfo ); itemInfo.hItem = hItem; itemInfo.pszInvariant = szBuffer; itemInfo.cchInvariantMax = ARRAYSIZE( szBuffer ); itemInfo.mask = NIMF_PARAM | NIMF_TEXTINVARIANT | NIMF_IMAGE; if ( MLNavItem_GetInfo( hLibrary, &itemInfo ) != FALSE && Navigation_CheckInvariantName( szBuffer ) != FALSE ) { OmService *service = (OmService *)itemInfo.lParam; itemInfo.mask = NIMF_PARAM; itemInfo.lParam = 0L; MLNavItem_SetInfo( hLibrary, &itemInfo ); service->Release(); } } BOOL Navigation_ProcessMessage( INT msg, INT_PTR param1, INT_PTR param2, INT_PTR param3, INT_PTR *result ) { if (msg < ML_MSG_TREE_BEGIN || msg > ML_MSG_TREE_END) return FALSE; switch ( msg ) { case ML_MSG_TREE_ONCREATEVIEW: { HWND hView = NULL; HRESULT hr = Navigation_CreateView( Navigation_GetMessageItem( msg, param1 ), (HWND)param2, &hView ); *result = ( SUCCEEDED( hr ) ) ? (INT_PTR)hView : NULL; return TRUE; } case ML_MSG_NAVIGATION_ONDESTROY: Navigation_OnDestroy(); return TRUE; case ML_MSG_NAVIGATION_ONDELETE: Navigation_OnDeleteItem( Navigation_GetMessageItem( msg, param1 ) ); return TRUE; } return FALSE; }