mirror of
https://github.com/WinampDesktop/winamp.git
synced 2024-09-24 15:54:12 +00:00
421 lines
11 KiB
C++
421 lines
11 KiB
C++
|
#include <strsafe.h>
|
||
|
|
||
|
#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;
|
||
|
}
|