Initial community commit

This commit is contained in:
Jef
2024-09-24 14:54:57 +02:00
parent 537bcbc862
commit 20d28e80a5
16810 changed files with 4640254 additions and 2 deletions
+220
View File
@@ -0,0 +1,220 @@
#define PLUGIN_VER L"2.08"
#include "main.h"
#include "tagger.h"
#include "../nu/MediaLibraryInterface.h"
api_language *WASABI_API_LNG = 0;
HINSTANCE WASABI_API_LNG_HINST = 0, WASABI_API_ORIG_HINST = 0;
api_gracenote *AGAVE_API_GRACENOTE = 0;
api_decodefile *AGAVE_API_DECODE = 0;
api_mldb *AGAVE_API_MLDB = 0;
static int Init();
static void Quit();
extern "C" winampMediaLibraryPlugin plugin =
{
MLHDR_VER,
"nullsoft(ml_autotag.dll)",
Init,
Quit,
PluginMessageProc,
0,
0,
0,
};
template <class api_T>
void ServiceBuild(api_T *&api_t, GUID factoryGUID_t)
{
if (plugin.service)
{
waServiceFactory *factory = plugin.service->service_getServiceByGuid(factoryGUID_t);
if (factory)
api_t = reinterpret_cast<api_T *>( factory->getInterface() );
}
}
const char *INI_FILE=0;
int Init()
{
mediaLibrary.library = plugin.hwndLibraryParent;
mediaLibrary.winamp = plugin.hwndWinampParent;
mediaLibrary.instance = plugin.hDllInstance;
INI_FILE = mediaLibrary.GetWinampIni();
ServiceBuild( AGAVE_API_GRACENOTE, gracenoteApiGUID );
ServiceBuild( AGAVE_API_DECODE, decodeFileGUID );
ServiceBuild( WASABI_API_LNG, languageApiGUID );
ServiceBuild( AGAVE_API_MLDB, mldbApiGuid );
if ( !AGAVE_API_GRACENOTE || !AGAVE_API_DECODE || !WASABI_API_LNG )
return ML_INIT_FAILURE; // error!
WASABI_API_START_LANG( plugin.hDllInstance, MlAutoTagLangGUID );
static wchar_t szDescription[256];
swprintf( szDescription, ARRAYSIZE( szDescription ), WASABI_API_LNGSTRINGW( IDS_PLUGINNAME ), PLUGIN_VER );
plugin.description = (char*)szDescription;
return ML_INIT_SUCCESS;
}
void Quit()
{
}
void LookupTracks(std::vector<TagItem*> &list, HWND parent=0)
{
if(!AGAVE_API_MLDB)
{
ServiceBuild(AGAVE_API_MLDB, mldbApiGuid);
if(!AGAVE_API_MLDB) return;
}
if(!parent) parent = plugin.hwndLibraryParent;
ICDDBMusicIDManager3 *musicid = AGAVE_API_GRACENOTE?AGAVE_API_GRACENOTE->GetMusicID():NULL;
if(!musicid)
{
wchar_t title[32] = {0};
MessageBoxW(parent,WASABI_API_LNGSTRINGW(IDS_GRACENOTE_TOOLS_NOT_INSTALLED),
WASABI_API_LNGSTRINGW_BUF(IDS_ERROR,title, 32),0);
return;
}
//parent = 0; // non-blocking...
// as we're not parenting directly, then we have a look at the aot state and fiddle it
// -> not ideal but at least the dialog will show on top so it can be seen initially
HWND dialog = WASABI_API_CREATEDIALOGPARAMW(IDD_AUTOTAGGER,parent,autotagger_dlgproc,(LPARAM)new Tagger(list, musicid));
if(GetWindowLongPtr(plugin.hwndWinampParent,GWL_EXSTYLE) & WS_EX_TOPMOST)
SetWindowPos(dialog, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE);
}
static bool IsInternetAvailable()
{
return !!SendMessage(plugin.hwndWinampParent, WM_WA_IPC, 0, IPC_INETAVAILABLE);
}
INT_PTR PluginMessageProc(int message_type, INT_PTR param1, INT_PTR param2, INT_PTR param3)
{
if (message_type == ML_MSG_NO_CONFIG)
{
return TRUE;
}
else if (message_type == ML_MSG_ONSENDTOBUILD)
{
if ((param1 == ML_TYPE_ITEMRECORDLIST || param1 == ML_TYPE_FILENAMES ||
param1 == ML_TYPE_STREAMNAMES || param1 == ML_TYPE_ITEMRECORDLISTW ||
param1 == ML_TYPE_FILENAMESW || param1 == ML_TYPE_STREAMNAMESW) &&
IsInternetAvailable())
{
mediaLibrary.AddToSendTo(WASABI_API_LNGSTRINGW(IDS_AUTOTAG), param2, (INT_PTR)PluginMessageProc);
}
}
else if (message_type == ML_MSG_ONSENDTOSELECT)
{
if (param3 != (INT_PTR)PluginMessageProc) return 0;
INT_PTR type = param1;
INT_PTR data = param2;
if (data)
{
if (type == ML_TYPE_ITEMRECORDLISTW)
{
std::vector<TagItem*> list;
itemRecordListW *p = (itemRecordListW*)data;
for (int x = 0; x < p->Size; x ++)
{
list.push_back(new TagItem(p->Items[x].filename));
}
LookupTracks(list);
//list.deleteAll();
for (auto obj : list)
{
delete obj;
}
list.clear();
return 1;
}
else if (type == ML_TYPE_ITEMRECORDLIST)
{
std::vector<TagItem*> list;
itemRecordList *p = (itemRecordList*)data;
for (int x = 0; x < p->Size; x ++)
{
list.push_back(new TagItem(p->Items[x].filename));
}
LookupTracks(list);
//list.deleteAll();
for (auto obj : list)
{
delete obj;
}
list.clear();
return 1;
}
else if (type == ML_TYPE_FILENAMESW || type == ML_TYPE_STREAMNAMESW)
{
std::vector<TagItem*> list;
wchar_t *p = (wchar_t*)data;
while (p && *p)
{
list.push_back(new TagItem(p));
p += wcslen(p) + 1;
}
LookupTracks(list);
//list.deleteAll();
for (auto obj : list)
{
delete obj;
}
list.clear();
return 1;
}
else if (type == ML_TYPE_FILENAMES || type == ML_TYPE_STREAMNAMES)
{
std::vector<TagItem*> list;
char *p = (char*)data;
while (p && *p)
{
list.push_back(new TagItem(p));
p += strlen(p) + 1;
}
LookupTracks(list);
//list.deleteAll();
for (auto obj : list)
{
delete obj;
}
list.clear();
return 1;
}
}
}
return 0;
}
extern "C"
{
__declspec(dllexport) winampMediaLibraryPlugin *winampGetMediaLibraryPlugin()
{
return &plugin;
}
__declspec(dllexport) int winampUninstallPlugin(HINSTANCE hDllInst, HWND hwndDlg, int param) {
// allow an on-the-fly removal (since we've got to be with a compatible client build)
return ML_PLUGIN_UNINSTALL_NOW;
}
}
+35
View File
@@ -0,0 +1,35 @@
#ifndef NULLSOFT_ML_AUTOTAG_MAIN_H
#define NULLSOFT_ML_AUTOTAG_MAIN_H
#include <windows.h>
#include <shlwapi.h>
#include "../../General/gen_ml/ml.h"
#include "../nu/AutoWide.h"
#include "../nu/listview.h"
#include "resource.h"
#include <api/service/waServiceFactory.h>
#include "../gracenote/api_gracenote.h"
extern api_gracenote * gracenoteApi;
#define AGAVE_API_GRACENOTE gracenoteApi
#include "../Winamp/api_decodefile.h"
extern api_decodefile *decodeApi;
#define AGAVE_API_DECODE decodeApi
#include "../ml_local/api_mldb.h"
extern api_mldb *mldbApi;
#define AGAVE_API_MLDB mldbApi
#include "../Agave/Language/api_language.h"
extern winampMediaLibraryPlugin plugin;
INT_PTR PluginMessageProc(int message_type, INT_PTR param1, INT_PTR param2, INT_PTR param3);
LRESULT SetFileInfo(const wchar_t *filename, const wchar_t *metadata, const wchar_t *data);
void WriteFileInfo(const wchar_t *file);
int GetFileInfo(const wchar_t *filename, const wchar_t *metadata, wchar_t *dest, int len);
#endif
@@ -0,0 +1,25 @@
#include "main.h"
#include "../winamp/wa_ipc.h"
LRESULT SetFileInfo(const wchar_t *filename, const wchar_t *metadata, const wchar_t *data)
{
extendedFileInfoStructW efis = {
filename,
metadata,
data ? data : L"",
data ? (size_t)lstrlenW(data) : 0,
};
return SendMessage(plugin.hwndWinampParent, WM_WA_IPC, (WPARAM)&efis, IPC_SET_EXTENDED_FILE_INFOW);
}
void WriteFileInfo(const wchar_t *file)
{
SendMessage(plugin.hwndWinampParent, WM_WA_IPC, 0, IPC_WRITE_EXTENDED_FILE_INFO);
SendMessage(plugin.hwndWinampParent, WM_WA_IPC, (WPARAM)file, IPC_FILE_TAG_MAY_HAVE_UPDATEDW);
}
int GetFileInfo(const wchar_t *filename, const wchar_t *metadata, wchar_t *dest, int len)
{
extendedFileInfoStructW efis = { filename, metadata, dest, (size_t)len, };
return (int)(INT_PTR)SendMessage(plugin.hwndWinampParent, WM_WA_IPC, (WPARAM)&efis, IPC_GET_EXTENDED_FILE_INFOW_HOOKABLE); //will return 1 if wa2 supports this IPC call
}
@@ -0,0 +1,212 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"#include ""version.rc2""\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_AUTOTAGGER DIALOGEX 0, 0, 420, 318
STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Winamp Auto Tagger"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "Apply Changes",IDOK,296,297,62,14
PUSHBUTTON "Cancel",IDCANCEL,363,297,50,14
CONTROL "",IDC_LIST,"SysListView32",LVS_REPORT | LVS_ALIGNLEFT | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,7,7,406,157
GROUPBOX "Old Info",IDC_STATIC_OLDINFO,7,175,201,93
LTEXT "Title:",IDC_STATIC_TITLE_NEW,216,185,30,8
LTEXT "Track #:",IDC_STATIC_TRACK_NEW,216,194,30,8
LTEXT "Artist:",IDC_STATIC_ARTIST_NEW,216,203,30,8
LTEXT "Album:",IDC_STATIC_ALBUM_NEW,216,212,30,8
LTEXT "Genre:",IDC_STATIC_GENRE_NEW,216,221,30,8
LTEXT "Year:",IDC_STATIC_YEAR_NEW,216,230,30,8
LTEXT "",IDC_TITLE_NEW,246,185,162,8,SS_NOPREFIX
LTEXT "",IDC_TRACK_NEW,246,194,66,8
LTEXT "",IDC_ARTIST_NEW,246,203,162,8,SS_NOPREFIX
LTEXT "",IDC_ALBUM_NEW,246,212,162,8,SS_NOPREFIX
LTEXT "",IDC_GENRE_NEW,246,221,162,8,SS_NOPREFIX
LTEXT "",IDC_YEAR_NEW,246,230,66,8
GROUPBOX "New Info",IDC_STATIC_NEWINFO,212,175,201,93
LTEXT "Selected:",IDC_STATIC_FILENAME,7,165,31,8
LTEXT "filename",IDC_FILENAME,41,165,275,8,SS_PATHELLIPSIS
LTEXT "Disc #:",IDC_STATIC_DISC_NEW,312,194,30,8
LTEXT "",IDC_DISC_NEW,342,194,66,8
LTEXT "Title:",IDC_STATIC_TITLE_OLD,11,185,30,8
LTEXT "Track #:",IDC_STATIC_TRACK_OLD,11,194,30,8
LTEXT "Artist:",IDC_STATIC_ARTIST_OLD,11,203,30,8
LTEXT "Album:",IDC_STATIC_ALBUM_OLD,11,212,30,8
LTEXT "Genre:",IDC_STATIC_GENRE_OLD,11,221,30,8
LTEXT "Year:",IDC_STATIC_YEAR_OLD,11,230,30,8
LTEXT "",IDC_TITLE_OLD,41,185,162,8,SS_NOPREFIX
LTEXT "",IDC_TRACK_OLD,41,194,66,8
LTEXT "",IDC_ARTIST_OLD,41,203,162,8,SS_NOPREFIX
LTEXT "",IDC_ALBUM_OLD,41,212,162,8,SS_NOPREFIX
LTEXT "",IDC_GENRE_OLD,41,221,162,8,SS_NOPREFIX
LTEXT "",IDC_YEAR_OLD,41,230,66,8
LTEXT "Disc #:",IDC_STATIC_DISC_OLD,107,194,30,8
LTEXT "",IDC_DISC_OLD,137,194,66,8
PUSHBUTTON "Check All",IDC_CHECK_ALL,319,165,46,11
PUSHBUTTON "Check None",IDC_CHECK_NONE,367,165,46,11
LTEXT "Accessing Gracenote Media Database...",IDC_BRANDTXT,7,303,129,8,NOT WS_VISIBLE
LTEXT "Album Artist:",IDC_STATIC_ALBUMARTIST_OLD,11,239,42,8
LTEXT "Publisher:",IDC_STATIC_PUBLISHER_OLD,11,248,32,8
LTEXT "",IDC_PUBLISHER_OLD,49,248,154,8,SS_NOPREFIX
LTEXT "",IDC_ALBUMARTIST_OLD,55,239,148,8,SS_NOPREFIX
LTEXT "Album Artist:",IDC_STATIC_ALBUMARTIST_NEW,216,239,42,8
LTEXT "Publisher:",IDC_STATIC_PUBLISHER_NEW,216,248,32,8
LTEXT "",IDC_PUBLISHER_NEW,254,248,154,8,SS_NOPREFIX
LTEXT "",IDC_ALBUMARTIST_NEW,260,239,148,8,SS_NOPREFIX
LTEXT "Composer:",IDC_STATIC_COMPOSER_OLD,11,257,36,8
LTEXT "",IDC_COMPOSER_OLD,49,257,154,8,SS_NOPREFIX
LTEXT "Composer:",IDC_STATIC_COMPOSER_NEW,216,257,36,8
LTEXT "",IDC_COMPOSER_NEW,254,257,154,8,SS_NOPREFIX
LTEXT "BPM:",IDC_STATIC_BPM_OLD,108,230,17,8
LTEXT "",IDC_BPM_OLD,138,230,66,8
LTEXT "BPM:",IDC_STATIC_BPM_NEW,312,230,17,8
LTEXT "",IDC_BPM_NEW,342,230,66,8
END
IDD_SAVING DIALOGEX 0, 0, 186, 45
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Updating Files..."
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
CONTROL "",IDC_PROGRESS,"msctls_progress32",WS_BORDER,7,7,172,14
DEFPUSHBUTTON "Cancel",IDCANCEL,68,24,50,14
END
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
IDD_AUTOTAGGER, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 413
TOPMARGIN, 7
BOTTOMMARGIN, 311
END
IDD_SAVING, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 179
TOPMARGIN, 7
BOTTOMMARGIN, 38
END
END
#endif // APSTUDIO_INVOKED
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// English (U.K.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
#pragma code_page(1252)
#endif //_WIN32
/////////////////////////////////////////////////////////////////////////////
//
// String Table
//
STRINGTABLE
BEGIN
IDS_PLUGINNAME "Nullsoft Auto-Tagger v%s"
65535 "{D8DBA660-90BD-431d-8F4E-189D6ACB407E}"
END
STRINGTABLE
BEGIN
IDS_GRACENOTE_TOOLS_NOT_INSTALLED "Gracenote tools are not installed"
IDS_ERROR "Error"
IDS_FILENAME "Filename"
IDS_STATUS "Status"
IDS_PROCESSING "Processing..."
IDS_LOOKINGUP "Looking up..."
IDS_QUERYING "Querying..."
IDS_QUERIED "Queried"
IDS_PROCESSED "Done"
END
STRINGTABLE
BEGIN
IDS_ANALYZING "Analyzing..."
IDS_WAITING "Waiting"
IDS_NOMATCH "No Match"
IDS_AUTOTAG "Auto-Tag"
IDS_FUZZY "Unsure"
END
#endif // English (U.K.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
#include "version.rc2"
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED
@@ -0,0 +1,30 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29509.3
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ml_autotag", "ml_autotag.vcxproj", "{11598486-4F4A-4D6A-BE12-A66B71ED8730}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Release|Win32 = Release|Win32
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{11598486-4F4A-4D6A-BE12-A66B71ED8730}.Debug|Win32.ActiveCfg = Debug|Win32
{11598486-4F4A-4D6A-BE12-A66B71ED8730}.Debug|Win32.Build.0 = Debug|Win32
{11598486-4F4A-4D6A-BE12-A66B71ED8730}.Debug|x64.ActiveCfg = Debug|x64
{11598486-4F4A-4D6A-BE12-A66B71ED8730}.Debug|x64.Build.0 = Debug|x64
{11598486-4F4A-4D6A-BE12-A66B71ED8730}.Release|Win32.ActiveCfg = Release|Win32
{11598486-4F4A-4D6A-BE12-A66B71ED8730}.Release|Win32.Build.0 = Release|Win32
{11598486-4F4A-4D6A-BE12-A66B71ED8730}.Release|x64.ActiveCfg = Release|x64
{11598486-4F4A-4D6A-BE12-A66B71ED8730}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {21C6579D-AAA7-4D78-A13A-7B5536E8F0E2}
EndGlobalSection
EndGlobal
@@ -0,0 +1,306 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{11598486-4F4A-4D6A-BE12-A66B71ED8730}</ProjectGuid>
<RootNamespace>ml_autotag</RootNamespace>
<WindowsTargetPlatformVersion>10.0.19041.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
<IncludePath>$(IncludePath)</IncludePath>
<LibraryPath>$(LibraryPath)</LibraryPath>
<EmbedManifest>true</EmbedManifest>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
<EmbedManifest>true</EmbedManifest>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
<IncludePath>$(IncludePath)</IncludePath>
<LibraryPath>$(LibraryPath)</LibraryPath>
<EmbedManifest>true</EmbedManifest>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
<EmbedManifest>true</EmbedManifest>
</PropertyGroup>
<PropertyGroup Label="Vcpkg">
<VcpkgEnableManifest>false</VcpkgEnableManifest>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<VcpkgInstalledDir>
</VcpkgInstalledDir>
<VcpkgUseStatic>false</VcpkgUseStatic>
<VcpkgConfiguration>Debug</VcpkgConfiguration>
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<VcpkgInstalledDir>
</VcpkgInstalledDir>
<VcpkgUseStatic>false</VcpkgUseStatic>
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<VcpkgInstalledDir>
</VcpkgInstalledDir>
<VcpkgUseStatic>false</VcpkgUseStatic>
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
<VcpkgConfiguration>Debug</VcpkgConfiguration>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<VcpkgInstalledDir>
</VcpkgInstalledDir>
<VcpkgUseStatic>false</VcpkgUseStatic>
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\Wasabi;../;..\..\..\,./;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;WIN32;_DEBUG;_WINDOWS;_USRDLL;ML_AUTOTAG_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<BufferSecurityCheck>true</BufferSecurityCheck>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
</ClCompile>
<Link>
<AdditionalDependencies>comctl32.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
<SubSystem>Windows</SubSystem>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
<TargetMachine>MachineX86</TargetMachine>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
<PostBuildEvent>
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\
xcopy /Y /D $(IntDir)$(TargetName).pdb ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\ </Command>
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\'</Message>
</PostBuildEvent>
<ResourceCompile>
<PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
<Manifest>
<OutputManifestFile>$(IntDir)$(TargetName)$(TargetExt).intermediate.manifest</OutputManifestFile>
</Manifest>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\Wasabi;../;..\..\..\;./;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;WIN64;_DEBUG;_WINDOWS;_USRDLL;ML_AUTOTAG_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<BufferSecurityCheck>true</BufferSecurityCheck>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
</ClCompile>
<Link>
<AdditionalDependencies>comctl32.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
<SubSystem>Windows</SubSystem>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
<PostBuildEvent>
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\
xcopy /Y /D $(IntDir)$(TargetName).pdb ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\ </Command>
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\'</Message>
</PostBuildEvent>
<ResourceCompile>
<PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
<Manifest>
<OutputManifestFile>$(IntDir)$(TargetName)$(TargetExt).intermediate.manifest</OutputManifestFile>
</Manifest>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<Optimization>MinSpace</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<AdditionalIncludeDirectories>..\..\..\Wasabi;../;./;..\..\..\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;WIN32;NDEBUG;_WINDOWS;_USRDLL;ML_AUTOTAG_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>None</DebugInformationFormat>
<DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<BufferSecurityCheck>true</BufferSecurityCheck>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
</ClCompile>
<Link>
<AdditionalDependencies>comctl32.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<GenerateDebugInformation>false</GenerateDebugInformation>
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
<SubSystem>Windows</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
<TargetMachine>MachineX86</TargetMachine>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
<PostBuildEvent>
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\ </Command>
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\'</Message>
</PostBuildEvent>
<ResourceCompile>
<PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
<Manifest>
<OutputManifestFile>$(IntDir)$(TargetName)$(TargetExt).intermediate.manifest</OutputManifestFile>
</Manifest>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<Optimization>MinSpace</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<AdditionalIncludeDirectories>..\..\..\Wasabi;../;./;..\..\..\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;WIN64;NDEBUG;_WINDOWS;_USRDLL;ML_AUTOTAG_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>None</DebugInformationFormat>
<DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<BufferSecurityCheck>true</BufferSecurityCheck>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
</ClCompile>
<Link>
<AdditionalDependencies>comctl32.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<GenerateDebugInformation>false</GenerateDebugInformation>
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
<SubSystem>Windows</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
<PostBuildEvent>
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\ </Command>
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\'</Message>
</PostBuildEvent>
<ResourceCompile>
<PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
<Manifest>
<OutputManifestFile>$(IntDir)$(TargetName)$(TargetExt).intermediate.manifest</OutputManifestFile>
</Manifest>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\General\gen_ml\ml_lib.cpp" />
<ClCompile Include="..\..\..\nu\listview.cpp" />
<ClCompile Include="..\..\..\nu\MediaLibraryInterface.cpp" />
<ClCompile Include="main.cpp" />
<ClCompile Include="metadata.cpp" />
<ClCompile Include="tagger.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\nu\listview.h" />
<ClInclude Include="..\..\..\nu\MediaLibraryInterface.h" />
<ClInclude Include="main.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="tagger.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="ml_autotag.rc" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\Wasabi\Wasabi.vcxproj">
<Project>{3e0bfa8a-b86a-42e9-a33f-ec294f823f7f}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
@@ -0,0 +1,71 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="metadata.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="tagger.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\..\nu\listview.cpp">
<Filter>Source Files\nu</Filter>
</ClCompile>
<ClCompile Include="..\..\..\nu\MediaLibraryInterface.cpp">
<Filter>Source Files\nu</Filter>
</ClCompile>
<ClCompile Include="..\..\General\gen_ml\ml_lib.cpp">
<Filter>Source Files\gen_ml</Filter>
</ClCompile>
<ClCompile Include="..\..\..\nu\PtrList.cpp">
<Filter>Source Files\nu</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="tagger.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="resource.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="main.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\nu\listview.h">
<Filter>Header Files\nu</Filter>
</ClInclude>
<ClInclude Include="..\..\..\nu\MediaLibraryInterface.h">
<Filter>Header Files\nu</Filter>
</ClInclude>
<ClInclude Include="..\..\..\nu\PtrList.h">
<Filter>Header Files\nu</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="Header Files">
<UniqueIdentifier>{eb7beaf8-5c4e-4515-9669-3cc08c4dec13}</UniqueIdentifier>
</Filter>
<Filter Include="Ressource Files">
<UniqueIdentifier>{e6fc722a-5751-4702-83f9-30ecc7e9576d}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files">
<UniqueIdentifier>{f0f150ed-27bc-470e-a3c6-76379e7aac57}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\nu">
<UniqueIdentifier>{0d3a7eae-c815-4473-bb08-27e49076c914}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\gen_ml">
<UniqueIdentifier>{3c9bf4d3-acf3-4085-97c0-7ea53dfcc512}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\nu">
<UniqueIdentifier>{5ae344c0-3796-4ce7-ba60-46ce8c1d188a}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="ml_autotag.rc">
<Filter>Ressource Files</Filter>
</ResourceCompile>
</ItemGroup>
</Project>
+88
View File
@@ -0,0 +1,88 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by ml_autotag.rc
//
#define IDD_AUTOTAGGER 101
#define IDS_GRACENOTE_TOOLS_NOT_INSTALLED 103
#define IDS_ERROR 104
#define IDS_FILENAME 105
#define IDS_STATUS 106
#define IDS_PROCESSING 107
#define IDS_LOOKINGUP 108
#define IDS_QUERYING 109
#define IDS_QUERIED 110
#define IDS_PROCESSED 111
#define IDS_ANALYZING 112
#define IDS_WAITING 113
#define IDS_NOMATCH 114
#define IDD_SAVING 114
#define IDS_AUTOTAG 116
#define IDS_FUZZY 117
#define IDC_LIST1 1001
#define IDC_LIST 1001
#define IDC_BUTTON1 1002
#define IDC_CHECK_ALL 1002
#define IDC_BUTTON2 1003
#define IDC_CHECK_NONE 1003
#define IDC_TITLE_OLD 1004
#define IDC_TRACK_OLD 1005
#define IDC_ARTIST_OLD 1006
#define IDC_ALBUM_OLD 1007
#define IDC_GENRE_OLD 1008
#define IDC_YEAR_OLD 1009
#define IDC_DISC_OLD 1010
#define IDC_STATIC_TITLE_OLD 1011
#define IDC_STATIC_TRACK_OLD 1012
#define IDC_STATIC_ARTIST_OLD 1013
#define IDC_STATIC_ALBUM_OLD 1014
#define IDC_STATIC_GENRE_OLD 1015
#define IDC_STATIC_YEAR_OLD 1016
#define IDC_STATIC_DISC_OLD 1017
#define IDC_TITLE_NEW 1018
#define IDC_TRACK_NEW 1019
#define IDC_DISC_NEW 1020
#define IDC_ARTIST_NEW 1021
#define IDC_ALBUM_NEW 1022
#define IDC_GENRE_NEW 1023
#define IDC_YEAR_NEW 1024
#define IDC_STATIC_DISC_NEW 1025
#define IDC_STATIC_TITLE_NEW 1026
#define IDC_STATIC_TRACK_NEW 1027
#define IDC_STATIC_ARTIST_NEW 1028
#define IDC_STATIC_ALBUM_NEW 1029
#define IDC_STATIC_GENRE_NEW 1030
#define IDC_STATIC_YEAR_NEW 1031
#define IDC_FILENAME 1032
#define IDC_STATIC_FILENAME 1033
#define IDC_STATIC_OLDINFO 1034
#define IDC_STATIC_NEWINFO 1035
#define IDC_PROGRESS 1036
#define IDC_PUBLISHER_OLD 1036
#define IDC_BRANDTXT 1037
#define IDC_ALBUMARTIST_OLD 1038
#define IDC_STATIC_ALBUMARTIST_OLD 1039
#define IDC_STATIC_PUBLISHER_OLD 1040
#define IDC_STATIC_ALBUMARTIST_NEW 1041
#define IDC_STATIC_PUBLISHER_NEW 1042
#define IDC_PUBLISHER_NEW 1043
#define IDC_ALBUMARTIST_NEW 1044
#define IDC_STATIC_COMPOSER_OLD 1045
#define IDC_COMPOSER_OLD 1046
#define IDC_STATIC_COMPOSER_NEW 1047
#define IDC_COMPOSER_NEW 1048
#define IDC_STATIC_BPM_OLD 1049
#define IDC_BPM_OLD 1050
#define IDC_STATIC_BPM_NEW 1051
#define IDC_BPM_NEW 1052
#define IDS_PLUGINNAME 65534
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 118
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1041
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
+831
View File
@@ -0,0 +1,831 @@
#include "main.h"
#include "tagger.h"
#define COL_FILENAME 0
#define COL_STATUS 1
static INT_PTR CALLBACK autotagger_saving_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
static const int ids[] =
{
IDC_TITLE_OLD,
IDC_TRACK_OLD,
IDC_ARTIST_OLD,
IDC_ALBUM_OLD,
IDC_GENRE_OLD,
IDC_YEAR_OLD,
IDC_DISC_OLD,
IDC_PUBLISHER_OLD,
IDC_ALBUMARTIST_OLD,
IDC_COMPOSER_OLD,
IDC_BPM_OLD,
IDC_TITLE_NEW,
IDC_TRACK_NEW,
IDC_ARTIST_NEW,
IDC_ALBUM_NEW,
IDC_GENRE_NEW,
IDC_YEAR_NEW,
IDC_DISC_NEW,
IDC_PUBLISHER_NEW,
IDC_ALBUMARTIST_NEW,
IDC_COMPOSER_NEW,
IDC_BPM_NEW,
IDC_FILENAME,
};
static const int ids_static[] =
{
IDC_STATIC_OLDINFO,
IDC_STATIC_TITLE_OLD,
IDC_STATIC_TRACK_OLD,
IDC_STATIC_ARTIST_OLD,
IDC_STATIC_ALBUM_OLD,
IDC_STATIC_GENRE_OLD,
IDC_STATIC_YEAR_OLD,
IDC_STATIC_DISC_OLD,
IDC_STATIC_ALBUMARTIST_OLD,
IDC_STATIC_PUBLISHER_OLD,
IDC_STATIC_COMPOSER_OLD,
IDC_STATIC_BPM_OLD,
IDC_STATIC_NEWINFO,
IDC_STATIC_DISC_NEW,
IDC_STATIC_TITLE_NEW,
IDC_STATIC_TRACK_NEW,
IDC_STATIC_ARTIST_NEW,
IDC_STATIC_ALBUM_NEW,
IDC_STATIC_GENRE_NEW,
IDC_STATIC_YEAR_NEW,
IDC_STATIC_ALBUMARTIST_NEW,
IDC_STATIC_PUBLISHER_NEW,
IDC_STATIC_COMPOSER_NEW,
IDC_STATIC_BPM_NEW,
IDC_STATIC_FILENAME,
};
static bool GetRole(ICddbDisc *disc, BSTR roleId, BSTR *str)
{
if (!roleId || !*roleId)
return false;
if (!disc)
return false;
ICddbCreditsPtr credits;
disc->get_Credits(&credits);
if (credits)
{
long creditCount;
credits->get_Count(&creditCount);
for (long c = 0;c < creditCount;c++)
{
ICddbCreditPtr credit;
credits->GetCredit(c + 1, &credit);
if (credit)
{
BSTR thisRole;
credit->get_Id(&thisRole);
if (!wcscmp(thisRole, roleId))
{
credit->get_Name(str);
return true;
}
}
}
}
return false;
}
static void EnableBottomView(HWND hwndDlg, int enable)
{
for (int i=0; i<(sizeof(ids_static)/sizeof(int)); i++)
EnableWindow(GetDlgItem(hwndDlg,ids_static[i]),enable);
for (int i=0; i<(sizeof(ids)/sizeof(int)); i++)
SetDlgItemText(hwndDlg,ids[i],L"");
}
INT_PTR CALLBACK autotagger_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_INITDIALOG:
{
SetWindowLongPtr( hwndDlg, GWLP_USERDATA, (LONG)(LONG_PTR)lParam );
Tagger *t = (Tagger *)lParam;
t->hwndDlg = hwndDlg;
HWND hlist = GetDlgItem( hwndDlg, IDC_LIST );
t->listview.setwnd( hlist );
EnableBottomView( hwndDlg, FALSE );
ICddbFileInfoListPtr infolist;
infolist.CreateInstance( CLSID_CddbFileInfoList );
ListView_SetExtendedListViewStyle( GetDlgItem( hwndDlg, IDC_LIST ), LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP );
t->listview.AddCol( WASABI_API_LNGSTRINGW( IDS_FILENAME ), 475 );
t->listview.AddCol( WASABI_API_LNGSTRINGW( IDS_STATUS ), 100 );
for ( size_t i = 0; i < t->list.size(); i++ )
{
ICddbFileInfoPtr info;
info.CreateInstance( CLSID_CddbFileInfo );
info->put_Filename( (wchar_t *)t->list[ i ]->filename );
infolist->AddFileInfo( info );
t->list[ i ]->num = (int)i;
t->listview.InsertItem( (int)i, t->list[ i ]->filename, (LPARAM)t->list[ i ] );
t->listview.SetItemText( (int)i, COL_STATUS, WASABI_API_LNGSTRINGW( IDS_WAITING ) );
ListView_SetCheckState( hlist, (int)i, FALSE );
}
t->musicid->LibraryID( infolist, MUSICID_LOOKUP_ASYNC | MUSICID_RETURN_SINGLE | MUSICID_GET_TAG_FROM_APP | MUSICID_GET_FP_FROM_APP | MUSICID_PREFER_WF_MATCHES );
}
break;
case WM_NOTIFY:
switch (((LPNMHDR)lParam)->code)
{
case LVN_ITEMCHANGED:
{
LPNMLISTVIEW lv=(LPNMLISTVIEW)lParam;
if ((lv->uNewState ^ lv->uOldState) & LVIS_SELECTED)
SendMessage(hwndDlg,WM_USER,0,0);
}
break;
}
break;
case WM_USER:
{
int f = ListView_GetNextItem(GetDlgItem(hwndDlg,IDC_LIST),-1,LVIS_FOCUSED);
if (f < 0)
{
EnableBottomView(hwndDlg,FALSE);
return -1;
}
EnableBottomView(hwndDlg,TRUE);
Tagger * t = (Tagger *)(LONG_PTR)GetWindowLongPtr(hwndDlg,GWLP_USERDATA);
TagItem * ti = t->list[f];
SetDlgItemText(hwndDlg,IDC_FILENAME,ti->filename);
BSTR bstr = 0;
if (ti->oldTag)
{
ICddbFileTag2_5Ptr tag2_5 = NULL;
ti->oldTag->QueryInterface(&tag2_5);
#define PUTINFO(x,y) ti->oldTag->get_ ## x ##(&bstr); if(bstr && *bstr) SetDlgItemText(hwndDlg,y,bstr); if(bstr) SysFreeString(bstr); bstr=0;
#define PUTINFO2(x,y) if (tag2_5) { tag2_5->get_ ## x ##(&bstr); if(bstr && *bstr) SetDlgItemText(hwndDlg,y,bstr); if(bstr) SysFreeString(bstr); bstr=0; }
PUTINFO(Title, IDC_TITLE_OLD);
PUTINFO(TrackPosition, IDC_TRACK_OLD);
PUTINFO(LeadArtist, IDC_ARTIST_OLD);
PUTINFO(Album, IDC_ALBUM_OLD);
PUTINFO(Genre, IDC_GENRE_OLD);
PUTINFO(Year, IDC_YEAR_OLD);
PUTINFO(PartOfSet, IDC_DISC_OLD);
PUTINFO(Label, IDC_PUBLISHER_OLD);
PUTINFO2(DiscArtist, IDC_ALBUMARTIST_OLD);
PUTINFO2(Composer, IDC_COMPOSER_OLD);
PUTINFO(BeatsPerMinute, IDC_BPM_OLD);
#undef PUTINFO
#undef PUTINFO2
}
if (ti->newTag)
{
ICddbFileTag2_5Ptr tag2_5 = NULL;
ICddbDisc2_5Ptr pDisc2_5 = NULL;
ti->newTag->QueryInterface(&tag2_5);
if (ti->disc)
ti->disc->QueryInterface(&pDisc2_5);
#define PUTINFO(x,y) ti->newTag->get_ ## x ##(&bstr); if(bstr && *bstr) SetDlgItemText(hwndDlg,y,bstr); if(bstr) SysFreeString(bstr); bstr=0;
#define PUTINFO2(x,y) if (tag2_5) { tag2_5->get_ ## x ##(&bstr); if(bstr && *bstr) SetDlgItemText(hwndDlg,y,bstr); if(bstr) SysFreeString(bstr); bstr=0; }
#define PUTROLE(x,y) if (GetRole(ti->disc, x, &bstr) && bstr && *bstr) SetDlgItemText(hwndDlg,y,bstr); if(bstr) SysFreeString(bstr); bstr=0;
PUTINFO(Title, IDC_TITLE_NEW);
PUTINFO(TrackPosition, IDC_TRACK_NEW);
PUTINFO(LeadArtist, IDC_ARTIST_NEW);
PUTINFO(Album, IDC_ALBUM_NEW);
if (pDisc2_5 == NULL
|| (FAILED(pDisc2_5->get_V2GenreStringPrimaryByLevel(3, &bstr))
&& FAILED(pDisc2_5->get_V2GenreStringPrimaryByLevel(2, &bstr))
&& FAILED(pDisc2_5->get_V2GenreStringPrimaryByLevel(1, &bstr))
&& FAILED(pDisc2_5->get_V2GenreStringPrimary(&bstr)))
)
{
PUTINFO(Genre, IDC_GENRE_NEW);
}
if (bstr && *bstr)
SetDlgItemText(hwndDlg,IDC_GENRE_NEW,bstr);
if (bstr) SysFreeString(bstr); bstr=0;
PUTINFO(Year, IDC_YEAR_NEW);
PUTINFO(PartOfSet, IDC_DISC_NEW);
PUTINFO(Label, IDC_PUBLISHER_NEW);
PUTINFO2(DiscArtist, IDC_ALBUMARTIST_NEW);
PUTINFO2(Composer, IDC_COMPOSER_NEW);
PUTINFO(BeatsPerMinute, IDC_BPM_NEW);
#undef PUTINFO
#undef PUTINFO2
#undef PUTROLE
}
}
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_CHECK_NONE:
case IDC_CHECK_ALL:
{
BOOL check = (LOWORD(wParam) == IDC_CHECK_ALL);
HWND hlist = GetDlgItem(hwndDlg,IDC_LIST);
size_t l = ListView_GetItemCount(hlist);
for (size_t i=0; i < l; i++)
ListView_SetCheckState(hlist,(int)i,check);
}
break;
case IDOK:
if (WASABI_API_DIALOGBOXW(IDD_SAVING,hwndDlg,autotagger_saving_dlgproc))
break;
case IDCANCEL:
{
Tagger * t = (Tagger *)(LONG_PTR)GetWindowLongPtr(hwndDlg,GWLP_USERDATA);
t->abort=1;
t->musicid->LibraryIDStop(0);
//t->musicid->LibraryIDClear();
}
EndDialog(hwndDlg,0);
break;
}
break;
case WM_DESTROY:
{
Tagger * t = (Tagger *)(LONG_PTR)GetWindowLongPtr(hwndDlg,GWLP_USERDATA);
if (t->icp) t->icp->Unadvise(t->m_dwCookie);
t->musicid->Shutdown();
t->musicid->Release();
delete t;
}
break;
case WM_CLOSE:
return SendMessage(hwndDlg,WM_COMMAND,IDCANCEL,0);
}
return 0;
}
static INT_PTR CALLBACK autotagger_saving_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static int i;
switch (uMsg)
{
case WM_INITDIALOG:
{
i=0;
SetTimer(hwndDlg,0,20,NULL);
Tagger * t = (Tagger *)(LONG_PTR)GetWindowLongPtr(GetParent(hwndDlg),GWLP_USERDATA);
SendDlgItemMessage(hwndDlg,IDC_PROGRESS,PBM_SETRANGE,0,MAKELPARAM(0, t->list.size()));
}
break;
case WM_TIMER:
if (wParam == 0)
{
KillTimer(hwndDlg,0);
HWND hlist = GetDlgItem(GetParent(hwndDlg),IDC_LIST);
Tagger * t = (Tagger *)(LONG_PTR)GetWindowLongPtr(GetParent(hwndDlg),GWLP_USERDATA);
int n = (int)t->list.size();
for (;;)
{
if (i >= n)
{
EndDialog(hwndDlg,0);
return 0;
}
if (ListView_GetCheckState(hlist,i))
{
TagItem *ti = t->list[i];
const wchar_t *fn = ti->filename;
BSTR bstr=0;
if (ti->newTag)
{
ICddbFileTag2_5Ptr tag2_5 = NULL;
ICddbDisc2_5Ptr pDisc2_5 = NULL;
ti->newTag->QueryInterface(&tag2_5);
if (ti->disc)
ti->disc->QueryInterface(&pDisc2_5);
#define PUTINFO(x,y) ti->newTag->get_ ## x ## (&bstr); if(bstr && *bstr) SetFileInfo(fn,y,bstr); if(bstr) SysFreeString(bstr); bstr=0;
#define PUTINFO2(x,y) if (tag2_5) { tag2_5->get_ ## x ## (&bstr); if(bstr && *bstr) SetFileInfo(fn,y,bstr); if(bstr) SysFreeString(bstr); bstr=0; }
#define PUTROLE(x,y) if (GetRole(ti->disc, x, &bstr) && bstr && *bstr) SetFileInfo(fn,y,bstr); if(bstr) SysFreeString(bstr); bstr=0;
PUTINFO(LeadArtist, L"artist");
PUTINFO(Album, L"album");
PUTINFO(Title, L"title");
if (pDisc2_5 == NULL
|| (FAILED(pDisc2_5->get_V2GenreStringPrimaryByLevel(3, &bstr))
&& FAILED(pDisc2_5->get_V2GenreStringPrimaryByLevel(2, &bstr))
&& FAILED(pDisc2_5->get_V2GenreStringPrimaryByLevel(1, &bstr))
&& FAILED(pDisc2_5->get_V2GenreStringPrimary(&bstr)))
)
{
PUTINFO(Genre, L"genre");
}
if (bstr && *bstr)
SetFileInfo(fn,L"genre",bstr);
if (bstr) SysFreeString(bstr); bstr=0;
// benski> CUT: PUTINFO(Genre, L"genre");
PUTINFO(Year, L"year");
PUTINFO(Label, L"publisher");
PUTINFO(BeatsPerMinute, L"bpm");
PUTINFO(TrackPosition, L"track");
PUTINFO(PartOfSet, L"disc");
PUTINFO2(Composer, L"composer");
PUTINFO2(DiscArtist, L"albumartist");
PUTINFO(ISRC, L"ISRC");
//PUTROLE(L"147", L"remixing");
PUTINFO(FileId, L"GracenoteFileID");
PUTINFO2(ExtDataSerialized, L"GracenoteExtData");
WriteFileInfo(fn);
#undef PUTINFO
#undef PUTINFO2
#undef PUTROLE
}
i++;
SendDlgItemMessage(hwndDlg,IDC_PROGRESS,PBM_SETPOS,i,0);
SetTimer(hwndDlg,0,20,NULL);
return 0;
}
else i++;
SendDlgItemMessage(hwndDlg,IDC_PROGRESS,PBM_SETPOS,i,0);
}
}
break;
case WM_COMMAND:
if (LOWORD(wParam) == IDCANCEL) EndDialog(hwndDlg,1);
break;
case WM_CLOSE:
EndDialog(hwndDlg,1);
break;
}
return 0;
}
TagItem::TagItem(const char * filename0) : freefn(true), num(0)
{
filename = AutoWideDup(filename0);
init();
}
TagItem::TagItem(const wchar_t * filename0, bool copy) : freefn(copy), num(0)
{
filename = copy?_wcsdup(filename0):filename0;
init();
}
TagItem::~TagItem()
{
if (freefn) free((void*)filename);
}
void TagItem::init()
{
last_match = MUSICID_MATCH_NONE;
oldTag.CreateInstance(CLSID_CddbID3Tag);
}
void TagItem::SetStatus(CddbMusicIDStatus status, HWND hwndDlg)
{
int s[] = {0, IDS_ERROR, IDS_PROCESSING, IDS_LOOKINGUP, IDS_LOOKINGUP, 0, IDS_QUERYING, IDS_QUERIED, IDS_PROCESSING, IDS_PROCESSED, IDS_ANALYZING, IDS_QUERYING};
if (status < sizeof(s)/sizeof(int))
{
wchar_t buf[100] = {0};
SetStatus(WASABI_API_LNGSTRINGW_BUF(s[status],buf,100),hwndDlg);
}
}
void TagItem::SetStatus(const wchar_t *text, HWND hwndDlg)
{
LVITEM lvi = {0, };
lvi.iItem = num;
lvi.iSubItem = COL_STATUS;
lvi.mask = LVIF_TEXT;
lvi.pszText = (LPTSTR)text;
lvi.cchTextMax = lstrlenW(text);
SendMessageW(GetDlgItem(hwndDlg,IDC_LIST), LVM_SETITEMW, 0, (LPARAM)&lvi);
}
void TagItem::Check(HWND hwndDlg, BOOL check)
{
HWND hlist = GetDlgItem(hwndDlg,IDC_LIST);
ListView_SetCheckState(hlist,(WPARAM)num,(LPARAM)check);
}
void TagItem::TagUpdate(HWND hwndDlg)
{
int f = ListView_GetNextItem(GetDlgItem(hwndDlg,IDC_LIST),-1,LVIS_FOCUSED);
if (f == num)
SendMessage(hwndDlg,WM_USER,0,0);
}
static IConnectionPoint *GetConnectionPoint(IUnknown *punk, REFIID riid);
Tagger::Tagger(std::vector<TagItem*> &_list, ICDDBMusicIDManager3 *musicid) : hwndDlg(0), abort(0), musicid(musicid), icp(0), m_dwCookie(0)
{
//list.own(_list);
for (auto obj : list)
{
delete obj;
}
list.clear();
list.assign(_list.begin(), _list.end());
_list.clear();
icp = GetConnectionPoint(musicid, DIID__ICDDBMusicIDManagerEvents);
if (icp)
{
icp->Advise(static_cast<IDispatch *>(this), &m_dwCookie);
icp->Release();
}
}
Tagger::~Tagger()
{
}
TagItem *Tagger::FindTagItem( const wchar_t *filename )
{
if ( !filename )
return NULL;
for ( TagItem *l_tag_item : list )
if ( !_wcsicmp( l_tag_item->filename, filename ) )
return l_tag_item;
return NULL;
}
HRESULT Tagger::OnTrackIDStatusUpdate(CddbMusicIDStatus Status, BSTR filename, long* Abort)
{
TagItem *t = FindTagItem(filename);
if (t) t->SetStatus(Status,hwndDlg);
*Abort = abort;
return S_OK;
}
HRESULT Tagger::OnTrackIDComplete(CddbMusicIDMatchCode match_code, ICddbFileInfo* pInfoIn, ICddbFileInfoList* pListOut)
{
if (!pInfoIn || !pListOut)
return S_OK;
BSTR filename;
pInfoIn->get_Filename(&filename);
TagItem *t = FindTagItem(filename);
if (!t) return S_OK;
if (match_code == MUSICID_MATCH_FUZZY)
{
if (t->last_match == MUSICID_MATCH_EXACT)
return S_OK;
t->Check(hwndDlg, FALSE);
}
else if (match_code == MUSICID_MATCH_EXACT)
{
t->Check(hwndDlg, TRUE);
}
else if (match_code == MUSICID_MATCH_NONE)
{
if (t->last_match == MUSICID_MATCH_EXACT)
return S_OK;
}
t->last_match = match_code;
wchar_t buf[100] = {0};
switch(match_code)
{
case MUSICID_MATCH_NONE:
t->SetStatus(WASABI_API_LNGSTRINGW_BUF(IDS_NOMATCH,buf,100),hwndDlg);
return S_OK;
case MUSICID_MATCH_FUZZY:
t->SetStatus(WASABI_API_LNGSTRINGW_BUF(IDS_FUZZY,buf,100),hwndDlg);
break;
case MUSICID_MATCH_ERROR:
t->SetStatus(WASABI_API_LNGSTRINGW_BUF(IDS_ERROR,buf,100),hwndDlg);
return S_OK;
default:
t->SetStatus(WASABI_API_LNGSTRINGW_BUF(IDS_PROCESSED,buf,100),hwndDlg);
break;
}
/*
if (match_code <= 1)
{
t->SetStatus(WASABI_API_LNGSTRINGW_BUF(IDS_NOMATCH,buf,100),hwndDlg); return S_OK;
}
else t->SetStatus(WASABI_API_LNGSTRINGW_BUF(IDS_PROCESSED,buf,100),hwndDlg);
*/
long num;
pListOut->get_Count(&num);
if (!num) return S_OK;
ICddbFileInfoPtr infotag;
pListOut->GetFileInfo(1,&infotag);
if (infotag)
{
infotag->get_Disc(&t->disc);
infotag->get_Tag(&t->newTag);
t->TagUpdate(hwndDlg);
}
return S_OK;
}
HRESULT Tagger::OnAlbumIDStatusUpdate(CddbMusicIDStatus Status, BSTR filename, long current_file, long total_files, long* Abort)
{
TagItem *t = FindTagItem(filename);
if (t) t->SetStatus(Status,hwndDlg);
*Abort = abort;
return S_OK;
}
HRESULT Tagger::OnAlbumIDComplete(LONG match_code, ICddbFileInfoList* pListIn, ICddbFileInfoLists* pListsOut)
{
if (!pListIn || !pListsOut)
return 0;
long c1=0,c2=0;
pListIn->get_Count(&c1);
pListsOut->get_Count(&c2);
if (c2<=0) return 0;
for (int i=1; i<=c2; i++)
{
ICddbFileInfoListPtr list;
pListsOut->GetFileInfoList(i,&list);
list->get_Count(&c1);
for (int i=1; i<=c1; i++)
{
ICddbFileInfoPtr pInfoIn;
list->GetFileInfo(i,&pInfoIn);
ICddbFileInfoListPtr pListOut;
pListOut.CreateInstance(CLSID_CddbFileInfoList);
ICddbFileInfoPtr temp;
list->GetFileInfo(i,&temp);
pListOut->AddFileInfo(temp);
CddbMusicIDMatchCode match;
pInfoIn->get_MusicIDMatchCode(&match);
OnTrackIDComplete(match,pInfoIn,pListOut);
}
}
return S_OK;
}
HRESULT Tagger::OnLibraryIDListStarted(ICddbFileInfoList* pList, long FilesComplete, long FilesTotal, long FilesExact, long FilesFuzzy, long FilesNoMatch, long FilesError, long *Abort)
{
*Abort = abort;
ShowWindow(GetDlgItem(hwndDlg,IDC_BRANDTXT),SW_SHOWNA);
return S_OK;
}
HRESULT Tagger::OnLibraryIDListComplete(ICddbFileInfoList* pList, long FilesComplete, long FilesTotal, long FilesExact, long FilesFuzzy, long FilesNoMatch, long FilesError, long *Abort)
{
*Abort = abort;
return S_OK;
}
HRESULT Tagger::OnLibraryIDComplete(long FilesComplete, long FilesTotal, long FilesExact, long FilesFuzzy, long FilesNoMatch, long FilesError)
{
ShowWindow(GetDlgItem(hwndDlg,IDC_BRANDTXT),SW_HIDE);
return S_OK;
}
HRESULT Tagger::FillTag(ICddbFileInfo *info, BSTR filename)
{
TagItem *t = FindTagItem(filename);
if (!t) return E_FAIL;
ICddbID3Tag * infotag = t->oldTag;
ICddbFileTag2_5Ptr tag2_5 = NULL;
infotag->QueryInterface(&tag2_5);
itemRecordW *record = AGAVE_API_MLDB->GetFile(filename);
if (record && infotag && tag2_5)
{
wchar_t itemp[64] = {0};
#define PUTINFO(y, x) if(record-> ## x) infotag->put_ ## y ##(record-> ## x)
#define PUTINFOI(y, x) if(record-> ## x > 0) infotag->put_ ## y ##(_itow(record-> ## x,itemp,10))
#define PUTINFO2(y, x) if(record-> ## x) tag2_5->put_ ## y ##(record-> ## x)
PUTINFO(LeadArtist, artist);
PUTINFO(Album, album);
PUTINFO(Title, title);
PUTINFO(Genre, genre);
PUTINFOI(Year, year);
PUTINFO(Label, publisher);
PUTINFOI(BeatsPerMinute, bpm);
PUTINFOI(TrackPosition, track);
PUTINFOI(PartOfSet, disc);
PUTINFO2(Composer, composer);
PUTINFO2(DiscArtist, albumartist);
#undef PUTINFO
#undef PUTINFOI
#undef PUTINFO2
AGAVE_API_MLDB->FreeRecord(record);
}
else
{
wchar_t buf[2048]=L"";
#define PUTINFO(y, x) buf[0]=0; GetFileInfo(filename,x,buf,2048); if(buf[0]) if (infotag) infotag->put_ ## y ##(buf);
#define PUTINFO2(y, x) buf[0]=0; GetFileInfo(filename,x,buf,2048); if(buf[0]) if (tag2_5) tag2_5->put_ ## y ##(buf);
PUTINFO(LeadArtist, L"artist");
PUTINFO(Album, L"album");
PUTINFO(Title, L"title");
PUTINFO(Genre, L"genre");
PUTINFO(Year, L"year");
PUTINFO(Label, L"publisher");
PUTINFO(BeatsPerMinute, L"bpm");
PUTINFO(TrackPosition, L"track");
PUTINFO(PartOfSet, L"disc");
PUTINFO2(Composer, L"composer");
PUTINFO2(DiscArtist, L"albumartist");
#undef PUTINFO
#undef PUTINFO2
}
t->TagUpdate(hwndDlg);
info->put_Tag(infotag);
return S_OK;
}
// com shit
STDMETHODIMP STDMETHODCALLTYPE Tagger::QueryInterface(REFIID riid, PVOID *ppvObject)
{
if (!ppvObject)
return E_POINTER;
else if (IsEqualIID(riid, __uuidof(_ICDDBMusicIDManagerEvents)))
*ppvObject = (_ICDDBMusicIDManagerEvents *)this;
else if (IsEqualIID(riid, IID_IDispatch))
*ppvObject = (IDispatch *)this;
else if (IsEqualIID(riid, IID_IUnknown))
*ppvObject = this;
else
{
*ppvObject = NULL;
return E_NOINTERFACE;
}
AddRef();
return S_OK;
}
ULONG STDMETHODCALLTYPE Tagger::AddRef(void)
{
return 1;
}
ULONG STDMETHODCALLTYPE Tagger::Release(void)
{
return 0;
}
HRESULT STDMETHODCALLTYPE Tagger::Invoke(DISPID dispid, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS FAR *pdispparams, VARIANT FAR *pvarResult, EXCEPINFO FAR * pexecinfo, unsigned int FAR *puArgErr)
{
switch (dispid)
{
case 1: // OnTrackIDStatusUpdate, params: CddbMusicIDStatus Status, BSTR filename, long* Abort
{
long *abort = pdispparams->rgvarg[0].plVal;
BSTR filename = pdispparams->rgvarg[1].bstrVal;
if (!filename) return E_INVALIDARG;
CddbMusicIDStatus status = (CddbMusicIDStatus)pdispparams->rgvarg[2].lVal;
return OnTrackIDStatusUpdate(status,filename,abort);
}
case 2: // OnAlbumIDStatusUpdate, params: CddbMusicIDStatus Status, BSTR filename, long current_file, long total_files, long* Abort
{
long *abort = pdispparams->rgvarg[0].plVal;
long total_files = pdispparams->rgvarg[1].lVal;
long current_file= pdispparams->rgvarg[2].lVal;
CddbMusicIDStatus status = (CddbMusicIDStatus)pdispparams->rgvarg[4].lVal;
BSTR filename = pdispparams->rgvarg[3].bstrVal;
if (!filename) return E_INVALIDARG;
return OnAlbumIDStatusUpdate(status,filename,current_file,total_files,abort);
}
break;
case 3: // OnTrackIDComplete, params: LONG match_code, ICddbFileInfo* pInfoIn, ICddbFileInfoList* pListOut
{
IDispatch *disp1 =pdispparams->rgvarg[0].pdispVal;
IDispatch *disp2 =pdispparams->rgvarg[1].pdispVal;
if (!disp1 || !disp2) return E_INVALIDARG;
CddbMusicIDMatchCode match_code = (CddbMusicIDMatchCode)pdispparams->rgvarg[2].lVal;
ICddbFileInfoPtr pInfoIn;
ICddbFileInfoListPtr matchList;
disp1->QueryInterface(&matchList);
disp2->QueryInterface(&pInfoIn);
return OnTrackIDComplete(match_code,pInfoIn,matchList);
}
break;
case 4: // OnAlbumIDComplete, params: LONG match_code, ICddbFileInfoList* pListIn, ICddbFileInfoLists* pListsOut
{
IDispatch *disp1 =pdispparams->rgvarg[0].pdispVal;
IDispatch *disp2 =pdispparams->rgvarg[1].pdispVal;
if (!disp1 || !disp2) return E_INVALIDARG;
long match_code = pdispparams->rgvarg[2].lVal;
ICddbFileInfoListPtr pListIn;
ICddbFileInfoListsPtr pListsOut;
disp1->QueryInterface(&pListsOut);
disp2->QueryInterface(&pListIn);
return OnAlbumIDComplete(match_code,pListIn,pListsOut);
}
break;
case 7: // OnLibraryIDListStarted, params: ICddbFileInfoList* pList, long FilesComplete, long FilesTotal, long FilesExact, long FilesFuzzy, long FilesNoMatch, long FilesError, long *Abort
{
IDispatch *disp1 =pdispparams->rgvarg[7].pdispVal;
if (!disp1) return E_INVALIDARG;
ICddbFileInfoListPtr pList;
disp1->QueryInterface(&pList);
return OnLibraryIDListStarted(pList,pdispparams->rgvarg[6].lVal,pdispparams->rgvarg[5].lVal,pdispparams->rgvarg[4].lVal,pdispparams->rgvarg[3].lVal,pdispparams->rgvarg[2].lVal,pdispparams->rgvarg[1].lVal,pdispparams->rgvarg[0].plVal);
}
break;
case 8: // OnLibraryIDListComplete, params: ICddbFileInfoList* pList, long FilesComplete, long FilesTotal, long FilesExact, long FilesFuzzy, long FilesNoMatch, long FilesError, long *Abort
{
IDispatch *disp1 =pdispparams->rgvarg[7].pdispVal;
if (!disp1) return E_INVALIDARG;
ICddbFileInfoListPtr pList;
disp1->QueryInterface(&pList);
return OnLibraryIDListComplete(pList,pdispparams->rgvarg[6].lVal,pdispparams->rgvarg[5].lVal,pdispparams->rgvarg[4].lVal,pdispparams->rgvarg[3].lVal,pdispparams->rgvarg[2].lVal,pdispparams->rgvarg[1].lVal,pdispparams->rgvarg[0].plVal);
}
break;
case 9: // OnLibraryIDComplete, params: long FilesComplete, long FilesTotal, long FilesExact, long FilesFuzzy, long FilesNoMatch, long FilesError
{
return OnLibraryIDComplete(pdispparams->rgvarg[5].lVal,pdispparams->rgvarg[4].lVal,pdispparams->rgvarg[3].lVal,pdispparams->rgvarg[2].lVal,pdispparams->rgvarg[1].lVal,pdispparams->rgvarg[0].lVal);
}
break;
case 10: // OnGetFingerprintInfo
{
long *abort = pdispparams->rgvarg[0].plVal;
IDispatch *disp = pdispparams->rgvarg[1].pdispVal;
BSTR filename = pdispparams->rgvarg[2].bstrVal;
if (!disp || !filename) return E_INVALIDARG;
ICddbFileInfo *info;
disp->QueryInterface(&info);
HRESULT hr = AGAVE_API_GRACENOTE->CreateFingerprint(musicid, AGAVE_API_DECODE, info, filename, abort);
info->Release();
return hr;
}
break;
case 11: // OnGetTagInfo
{
//long *Abort = pdispparams->rgvarg[0].plVal;
IDispatch *disp = pdispparams->rgvarg[1].pdispVal;
BSTR filename = pdispparams->rgvarg[2].bstrVal;
if (!disp || !filename) return E_INVALIDARG;
ICddbFileInfo *info;
disp->QueryInterface(&info);
HRESULT hr = FillTag(info, filename);
info->Release();
return hr;
}
break;
}
return DISP_E_MEMBERNOTFOUND;
}
HRESULT STDMETHODCALLTYPE Tagger::GetIDsOfNames(REFIID riid, OLECHAR FAR* FAR* rgszNames, unsigned int cNames, LCID lcid, DISPID FAR* rgdispid)
{
*rgdispid = DISPID_UNKNOWN; return DISP_E_UNKNOWNNAME;
}
HRESULT STDMETHODCALLTYPE Tagger::GetTypeInfo(unsigned int itinfo, LCID lcid, ITypeInfo FAR* FAR* pptinfo)
{
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE Tagger::GetTypeInfoCount(unsigned int FAR * pctinfo)
{
return E_NOTIMPL;
}
static IConnectionPoint *GetConnectionPoint(IUnknown *punk, REFIID riid)
{
if (!punk)
return 0;
IConnectionPointContainer *pcpc=0;
IConnectionPoint *pcp = 0;
HRESULT hr = punk->QueryInterface(IID_IConnectionPointContainer, (void **) & pcpc);
if (SUCCEEDED(hr))
{
pcpc->FindConnectionPoint(riid, &pcp);
pcpc->Release();
}
return pcp;
}
+68
View File
@@ -0,0 +1,68 @@
#ifndef _NULLSOFT_AUTOTAGGER_TAGGER_H_
#define _NULLSOFT_AUTOTAGGER_TAGGER_H_
#include <vector>
class TagItem
{
public:
TagItem(const char * filename);
TagItem(const wchar_t * filename, bool copy=true);
~TagItem();
void init();
void SetStatus(CddbMusicIDStatus status, HWND hwndDlg);
void SetStatus(const wchar_t *str, HWND hwndDlg);
void TagUpdate(HWND hwndDlg);
void Check(HWND, BOOL);
const wchar_t *filename;
bool freefn;
int num;
CddbMusicIDMatchCode last_match;
ICddbID3TagPtr oldTag;
ICddbFileTagPtr newTag;
ICddbDisc2Ptr disc;
};
class Tagger : public _ICDDBMusicIDManagerEvents
{
public:
Tagger(std::vector<TagItem*> &list, ICDDBMusicIDManager3 *musicid); // 0 = trackid, 1 = albumid, 2 = libraryid
~Tagger();
TagItem* FindTagItem(const wchar_t * filename);
protected:
HRESULT OnTrackIDStatusUpdate(CddbMusicIDStatus Status, BSTR filename, long* Abort);
HRESULT OnAlbumIDStatusUpdate(CddbMusicIDStatus Status, BSTR filename, long current_file, long total_files, long* Abort);
HRESULT OnTrackIDComplete(CddbMusicIDMatchCode match_code, ICddbFileInfo* pInfoIn, ICddbFileInfoList* pListOut);
HRESULT OnAlbumIDComplete(LONG match_code, ICddbFileInfoList* pListIn, ICddbFileInfoLists* pListsOut);
HRESULT OnLibraryIDListStarted(ICddbFileInfoList* pList, long FilesComplete, long FilesTotal, long FilesExact, long FilesFuzzy, long FilesNoMatch, long FilesError, long *Abort);
HRESULT OnLibraryIDListComplete(ICddbFileInfoList* pList, long FilesComplete, long FilesTotal, long FilesExact, long FilesFuzzy, long FilesNoMatch, long FilesError, long *Abort);
HRESULT OnLibraryIDComplete(long FilesComplete, long FilesTotal, long FilesExact, long FilesFuzzy, long FilesNoMatch, long FilesError);
HRESULT FillTag(ICddbFileInfo *info, BSTR filename);
// com shit
STDMETHODIMP STDMETHODCALLTYPE QueryInterface(REFIID riid, PVOID *ppvObject);
ULONG STDMETHODCALLTYPE AddRef(void);
ULONG STDMETHODCALLTYPE Release(void);
HRESULT STDMETHODCALLTYPE Invoke(DISPID dispid, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS FAR *pdispparams, VARIANT FAR *pvarResult, EXCEPINFO FAR * pexecinfo, unsigned int FAR *puArgErr);
HRESULT STDMETHODCALLTYPE GetIDsOfNames(REFIID riid, OLECHAR FAR* FAR* rgszNames, unsigned int cNames, LCID lcid, DISPID FAR* rgdispid);
HRESULT STDMETHODCALLTYPE GetTypeInfo(unsigned int itinfo, LCID lcid, ITypeInfo FAR* FAR* pptinfo);
HRESULT STDMETHODCALLTYPE GetTypeInfoCount(unsigned int FAR * pctinfo);
public:
HWND hwndDlg;
std::vector<TagItem*> list;
ICDDBMusicIDManager3 *musicid;
long abort;
W_ListView listview;
IConnectionPoint *icp;
DWORD m_dwCookie;
};
extern INT_PTR CALLBACK autotagger_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
#endif // _NULLSOFT_AUTOTAGGER_TAGGER_H_
@@ -0,0 +1,39 @@
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
#include "../../../Winamp/buildType.h"
VS_VERSION_INFO VERSIONINFO
FILEVERSION 2,0,8,0
PRODUCTVERSION WINAMP_PRODUCTVER
FILEFLAGSMASK 0x17L
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x4L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "Winamp SA"
VALUE "FileDescription", "Winamp Media Library Plug-in"
VALUE "FileVersion", "2,0,8,0"
VALUE "InternalName", "Nullsoft Auto-Tagger"
VALUE "LegalCopyright", "Copyright © 2007-2023 Winamp SA"
VALUE "LegalTrademarks", "Nullsoft and Winamp are trademarks of Winamp SA"
VALUE "OriginalFilename", "ml_autotag.dll"
VALUE "ProductName", "Winamp"
VALUE "ProductVersion", STR_WINAMP_PRODUCTVER
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END
@@ -0,0 +1,15 @@
#ifndef NULLSOFT_API_ML_BOOKMARKS_H
#define NULLSOFT_API_ML_BOOKMARKS_H
#include "api/service/waServiceFactory.h"
#include "../Agave/Language/api_language.h"
#include "../Winamp/api_stats.h"
extern api_stats *statsApi;
#define AGAVE_API_STATS statsApi
#include "api/application/api_application.h"
#define WASABI_API_APP applicationApi
#endif // !NULLSOFT_API_ML_BOOKMARKS_H
@@ -0,0 +1,32 @@
/** (c) Nullsoft, Inc. C O N F I D E N T I A L
** Filename:
** Project:
** Description:
** Author:
** Created:
**/
#include "bookmark.h"
BookmarkWriter::BookmarkWriter():fp(0)
{
}
void BookmarkWriter::Open(const wchar_t *filename)
{
fp=_wfopen(filename, L"a+t");
}
void BookmarkWriter::New(const wchar_t *filename)
{
fp=_wfopen(filename, L"wt");
}
void BookmarkWriter::Write(const char *filename, const char *title)
{
fprintf(fp,"%s\n%s\n",filename,title);
}
void BookmarkWriter::Close()
{
if (fp) fclose(fp);
}
@@ -0,0 +1,18 @@
#ifndef NULLSOFT_BOOKMARKH
#define NULLSOFT_BOOKMARKH
#include <stdio.h>
class BookmarkWriter
{
public:
BookmarkWriter();
void New(const wchar_t *filename);
void Open(const wchar_t *filename);
void Write(const char *filename, const char *title);
void Close();
private:
FILE *fp;
};
#endif
@@ -0,0 +1,128 @@
/*
** Copyright (C) 2003 Nullsoft, Inc.
**
** This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held
** liable for any damages arising from the use of this software.
**
** Permission is granted to anyone to use this software for any purpose, including commercial applications, and to
** alter it and redistribute it freely, subject to the following restrictions:
**
** 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software.
** If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
**
** 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
**
** 3. This notice may not be removed or altered from any source distribution.
**
*/
#include <windows.h>
#include <commctrl.h>
#include "listview.h"
#ifdef GEN_ML_EXPORTS
#include "main.h" // for getting the font
#include "config.h"
#endif
// bp Comment: all the calls beginning "ListView_" are
// MACROs defined in commctrl.h
void W_ListView :: AddCol (char *text, int w)
{
LVCOLUMN lvc={0,};
lvc.mask = LVCF_TEXT|LVCF_WIDTH;
lvc.pszText = text;
if (w) lvc.cx=w;
ListView_InsertColumn (m_hwnd, m_col, &lvc);
m_col++;
}
int W_ListView::GetColumnWidth (int col)
{
if (col < 0 || col >= m_col) return 0;
return ListView_GetColumnWidth (m_hwnd, col);
}
int W_ListView::GetParam (int p)
{
LVITEM lvi={0,};
lvi.mask = LVIF_PARAM;
lvi.iItem = p;
ListView_GetItem (m_hwnd, &lvi);
return lvi.lParam;
}
int W_ListView::InsertItem (int p, char *text, int param)
{
LVITEM lvi={0,};
lvi.mask = LVIF_TEXT | LVIF_PARAM;
lvi.iItem = p;
lvi.pszText = text;
lvi.cchTextMax=strlen (text);
lvi.lParam = param;
return ListView_InsertItem (m_hwnd, &lvi);
}
void W_ListView::SetItemText (int p, int si, char *text)
{
LVITEM lvi={0,};
lvi.iItem = p;
lvi.iSubItem = si;
lvi.mask = LVIF_TEXT;
lvi.pszText = text;
lvi.cchTextMax = strlen (text);
ListView_SetItem (m_hwnd, &lvi);
}
void W_ListView::SetItemParam (int p, int param)
{
LVITEM lvi={0,};
lvi.iItem = p;
lvi.mask=LVIF_PARAM;
lvi.lParam=param;
ListView_SetItem (m_hwnd, &lvi);
}
void W_ListView::refreshFont ()
{
if (m_font)
{
DeleteFont (m_font);
SetWindowFont (m_hwnd, NULL, FALSE);
}
m_font = NULL;
HWND h;
#ifdef GEN_ML_EXPORTS
h=g_hwnd;
#else
h=m_libraryparent;
#endif
if (h && m_allowfonts)
{
int a=SendMessage (h, WM_USER+0x1000 /*WM_ML_IPC*/,66, 0x0600 /*ML_IPC_SKIN_WADLG_GETFUNC*/);
if (a)
{
m_font= (HFONT)a;
SetWindowFont (m_hwnd, m_font, FALSE);
}
}
InvalidateRect (m_hwnd, NULL, TRUE);
}
void W_ListView::setallowfonts (int allow)
{
m_allowfonts=allow;
}
void W_ListView::setwnd (HWND hwnd)
{
m_hwnd = hwnd;
if (hwnd)
{
ListView_SetExtendedListViewStyle (hwnd, LVS_EX_FULLROWSELECT|LVS_EX_UNDERLINEHOT );
refreshFont ();
}
}
+144
View File
@@ -0,0 +1,144 @@
/*
** Copyright (C) 2003 Nullsoft, Inc.
**
** This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held
** liable for any damages arising from the use of this software.
**
** Permission is granted to anyone to use this software for any purpose, including commercial applications, and to
** alter it and redistribute it freely, subject to the following restrictions:
**
** 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software.
** If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
**
** 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
**
** 3. This notice may not be removed or altered from any source distribution.
**
*/
#if 0
#ifndef _LISTVIEW_H_
#define _LISTVIEW_H_
#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
class W_ListView
{
public:
W_ListView()
{
m_hwnd=NULL;
m_col=0;
m_allowfonts=1;
m_font=NULL;
#ifndef GEN_ML_EXPORTS
m_libraryparent=NULL;
#endif
}
W_ListView(HWND hwnd)
{
m_hwnd=NULL;
m_col=0;
m_allowfonts=1;
m_font=NULL;
#ifndef GEN_ML_EXPORTS
m_libraryparent=NULL;
#endif
setwnd(hwnd);
}
~W_ListView()
{
if (m_font) DeleteFont(m_font);
m_font=0;
}
void refreshFont();
#ifndef GEN_ML_EXPORTS
void setLibraryParentWnd(HWND hwndParent)
{
m_libraryparent=hwndParent;
}// for Winamp Font getting stuff
#endif
void setallowfonts(int allow=1);
void setwnd(HWND hwnd);
void AddCol(char *text, int w);
int GetCount(void)
{
return ListView_GetItemCount(m_hwnd);
}
int GetParam(int p);
void DeleteItem(int n)
{
ListView_DeleteItem(m_hwnd,n);
}
void Clear(void)
{
ListView_DeleteAllItems(m_hwnd);
}
int GetSelected(int x)
{
return(ListView_GetItemState(m_hwnd, x, LVIS_SELECTED) & LVIS_SELECTED)?1:0;
}
int GetSelectedCount()
{
return ListView_GetSelectedCount(m_hwnd);
}
int GetSelectionMark()
{
return ListView_GetSelectionMark(m_hwnd);
}
void SetSelected(int x)
{
ListView_SetItemState(m_hwnd,x,LVIS_SELECTED,LVIS_SELECTED);
}
int InsertItem(int p, char *text, int param);
void GetItemRect(int i, RECT *r)
{
ListView_GetItemRect(m_hwnd, i, r, LVIR_BOUNDS);
}
void SetItemText(int p, int si, char *text);
void SetItemParam(int p, int param);
void GetText(int p, int si, char *text, int maxlen)
{
ListView_GetItemText(m_hwnd, p, si, text, maxlen);
}
int FindItemByParam(int param)
{
LVFINDINFO fi={LVFI_PARAM,0,param};
return ListView_FindItem(m_hwnd,-1,&fi);
}
int FindItemByPoint(int x, int y)
{
int l=GetCount();
for (int i=0;i<l;i++)
{
RECT r;
GetItemRect(i, &r);
if (r.left<=x && r.right>=x && r.top<=y && r.bottom>=y) return i;
}
return -1;
}
int GetColumnWidth(int col);
HWND getwnd(void)
{
return m_hwnd;
}
protected:
HWND m_hwnd;
HFONT m_font;
int m_col;
int m_allowfonts;
#ifndef GEN_ML_EXPORTS
HWND m_libraryparent;
#endif
};
#endif//_LISTVIEW_H_
#endif
+122
View File
@@ -0,0 +1,122 @@
//#define PLUGIN_NAME "Nullsoft Bookmarks"
#define PLUGIN_VERSION L"1.27"
#include "Main.h"
#include "../nu/AutoWide.h"
#include <strsafe.h>
#include "../../General/gen_ml/menu.h"
#include "../../General/gen_ml/ml_ipc_0313.h"
static int Init();
static void Quit();
extern "C" winampMediaLibraryPlugin plugin =
{
MLHDR_VER,
"nullsoft(ml_bookmarks.dll)",
Init,
Quit,
bm_pluginMessageProc,
0,
0,
0,
};
int bookmark_treeItem = 0;
HMENU g_context_menus, g_context_menus2;
HCURSOR hDragNDropCursor;
C_Config *g_config;
WNDPROC waProc=0;
// wasabi based services for localisation support
api_language *WASABI_API_LNG = 0;
HINSTANCE WASABI_API_LNG_HINST = 0, WASABI_API_ORIG_HINST = 0;
api_stats *AGAVE_API_STATS = 0;
api_application *WASABI_API_APP = 0;
static DWORD WINAPI wa_newWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
if (msg == WM_WA_IPC && lParam == IPC_ADDBOOKMARK && wParam && wParam != 666)
{
bookmark_notifyAdd(AutoWide((char*)wParam));
}
else if (msg == WM_WA_IPC && lParam == IPC_ADDBOOKMARKW && wParam && wParam != 666)
{
bookmark_notifyAdd((wchar_t*)wParam);
}
else if ((msg == WM_COMMAND || msg == WM_SYSCOMMAND) && LOWORD(wParam) == WINAMP_EDIT_BOOKMARKS)
{
mediaLibrary.ShowMediaLibrary();
mediaLibrary.SwitchToPluginView(bookmark_treeItem);
return 0;
}
if (waProc)
return (DWORD)CallWindowProcW(waProc, hwnd, msg, wParam, lParam);
else
return (DWORD)DefWindowProc(hwnd, msg, wParam, lParam);
}
int Init()
{
waProc = (WNDPROC)SetWindowLongPtrW( plugin.hwndWinampParent, GWLP_WNDPROC, (LONG_PTR)wa_newWndProc );
mediaLibrary.library = plugin.hwndLibraryParent;
mediaLibrary.winamp = plugin.hwndWinampParent;
mediaLibrary.instance = plugin.hDllInstance;
waServiceFactory *sf = plugin.service->service_getServiceByGuid( languageApiGUID );
if ( sf )
WASABI_API_LNG = reinterpret_cast<api_language *>( sf->getInterface() );
sf = plugin.service->service_getServiceByGuid( AnonymousStatsGUID );
if ( sf )
AGAVE_API_STATS = reinterpret_cast<api_stats *>( sf->getInterface() );
sf = plugin.service->service_getServiceByGuid( applicationApiServiceGuid );
if ( sf )
WASABI_API_APP = reinterpret_cast<api_application *>( sf->getInterface() );
// need to have this initialised before we try to do anything with localisation features
WASABI_API_START_LANG( plugin.hDllInstance, MlBookmarkLangGUID );
static wchar_t szDescription[ 256 ];
StringCchPrintfW( szDescription, ARRAYSIZE( szDescription ), WASABI_API_LNGSTRINGW( IDS_NULLSOFT_BOOKMARKS ), PLUGIN_VERSION );
plugin.description = (char *)szDescription;
wchar_t inifile[ MAX_PATH ] = { 0 };
mediaLibrary.BuildPath( L"Plugins", inifile, MAX_PATH );
CreateDirectoryW( inifile, NULL );
mediaLibrary.BuildPath( L"Plugins\\gen_ml.ini", inifile, MAX_PATH );
g_config = new C_Config( inifile );
g_context_menus = WASABI_API_LOADMENU( IDR_MENU1 );
g_context_menus2 = WASABI_API_LOADMENU( IDR_MENU1 );
hDragNDropCursor = LoadCursor( GetModuleHandle( L"gen_ml.dll" ), MAKEINTRESOURCE( ML_IDC_DRAGDROP ) );
NAVINSERTSTRUCT nis = { 0 };
nis.item.cbSize = sizeof( NAVITEM );
nis.item.pszText = WASABI_API_LNGSTRINGW( IDS_BOOKMARKS );
nis.item.pszInvariant = L"Bookmarks";
nis.item.mask = NIMF_TEXT | NIMF_TEXTINVARIANT | NIMF_IMAGE | NIMF_IMAGESEL;
nis.item.iSelectedImage = nis.item.iImage = mediaLibrary.AddTreeImageBmp( IDB_TREEITEM_BOOKMARKS );
// map to item id (will probably have to change but is a quick port to support invariant item naming)
NAVITEM nvItem = { sizeof( NAVITEM ),0,NIMF_ITEMID, };
nvItem.hItem = MLNavCtrl_InsertItem( plugin.hwndLibraryParent, &nis );
MLNavItem_GetInfo( plugin.hwndLibraryParent, &nvItem );
bookmark_treeItem = nvItem.id;
return 0;
}
void Quit()
{
delete g_config;
}
extern "C" __declspec(dllexport) winampMediaLibraryPlugin *winampGetMediaLibraryPlugin()
{
return &plugin;
}
+28
View File
@@ -0,0 +1,28 @@
#ifndef NULLSOFT_BOOKMARKS_MAIN_H
#define NULLSOFT_BOOKMARKS_MAIN_H
#include <windows.h>
#include <windowsx.h>
#include "api__ml_bookmarks.h"
#include "../Plugins/General/gen_ml/ml.h"
#include "../nu/MediaLibraryInterface.h"
#include "resource.h"
#include "../winamp/wa_ipc.h"
//#include "../Plugins/General/gen_ml/ml.h"
#include "../Plugins/General/gen_ml/config.h"
#define WINAMP_EDIT_BOOKMARKS 40320
INT_PTR bm_pluginMessageProc( int message_type, INT_PTR param1, INT_PTR param2, INT_PTR param3 );
extern winampMediaLibraryPlugin plugin;
extern int bookmark_treeItem;
void bookmark_notifyAdd( wchar_t *filenametitle );
#endif // !NULLSOFT_BOOKMARKS_MAIN_H
@@ -0,0 +1,186 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"#include ""version.rc2""\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Menu
//
IDR_MENU1 MENU
BEGIN
POPUP "BMWnd"
BEGIN
MENUITEM "Play selection\tEnter", ID_BMWND_PLAYSELECTEDFILES
MENUITEM "Enqueue selection\tShift+Enter", ID_BMWND_ENQUEUESELECTEDFILES
MENUITEM "Send to:", ID_BMWND_SENDTO
MENUITEM SEPARATOR
MENUITEM "Select all\tCtrl+A", ID_BMWND_SELECTALL
MENUITEM SEPARATOR
MENUITEM "Remove selected bookmarks\tDel", ID_BMWND_REMOVESELECTEDBOOKMARKS
MENUITEM "Edit selected bookmarks\tCtrl+E", ID_BMWND_EDITSELECTEDBOOKMARKS
END
POPUP "BMWndIcon"
BEGIN
MENUITEM "Play all bookmarks\tEnter", ID_BMWND_PLAYSELECTEDFILES
MENUITEM "Enqueue all bookmarks\tShift+Enter", ID_BMWND_ENQUEUESELECTEDFILES
MENUITEM SEPARATOR
MENUITEM "Help", ID_BMWND_HELP
END
END
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_VIEW_BM DIALOGEX 0, 0, 186, 92
STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN
EXSTYLE WS_EX_ACCEPTFILES | WS_EX_CONTROLPARENT
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
CONTROL "",IDC_LIST,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_NOSORTHEADER | WS_TABSTOP,0,0,184,79
CONTROL "Play",IDC_BUTTON_PLAY,"Button",BS_OWNERDRAW | WS_TABSTOP,0,81,35,11
CONTROL "Enqueue",IDC_BUTTON_ENQUEUE,"Button",BS_OWNERDRAW | WS_TABSTOP,38,81,35,11
CONTROL "Edit",IDC_EDITBOOK,"Button",BS_OWNERDRAW | WS_TABSTOP,76,81,36,11
CONTROL "Delete",IDC_REMOVEBOOK,"Button",BS_OWNERDRAW | WS_TABSTOP,114,81,36,11
END
IDD_EDITBOOKMARK DIALOGEX 0, 0, 241, 65
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Edit Bookmark"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
LTEXT "Title",IDC_STATIC,8,10,14,8,SS_CENTERIMAGE
EDITTEXT IDC_TITLE,28,7,206,14,ES_AUTOHSCROLL
LTEXT "File",IDC_STATIC,8,29,12,8,SS_CENTERIMAGE
EDITTEXT IDC_FILE,28,26,187,14,ES_AUTOHSCROLL
PUSHBUTTON "&...",IDC_EDIT_FN,218,25,16,15
DEFPUSHBUTTON "&OK",IDOK,6,44,50,14
PUSHBUTTON "&Cancel",IDCANCEL,60,44,50,14
END
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
IDD_EDITBOOKMARK, DIALOG
BEGIN
LEFTMARGIN, 6
RIGHTMARGIN, 234
TOPMARGIN, 7
BOTTOMMARGIN, 58
END
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Bitmap
//
IDB_TREEITEM_BOOKMARKS BITMAP "resources\\ti_bookmarks_16x16x16.bmp"
/////////////////////////////////////////////////////////////////////////////
//
// Accelerator
//
IDR_VIEW_BM_ACCELERATORS ACCELERATORS
BEGIN
"A", ID_BMWND_SELECTALL, VIRTKEY, CONTROL, NOINVERT
"E", ID_BMWND_EDITSELECTEDBOOKMARKS, VIRTKEY, CONTROL, NOINVERT
VK_DELETE, ID_BMWND_REMOVESELECTEDBOOKMARKS, VIRTKEY, NOINVERT
VK_RETURN, ID_BMWND_PLAYSELECTEDFILES, VIRTKEY, NOINVERT
VK_RETURN, ID_BMWND_ENQUEUESELECTEDFILES, VIRTKEY, SHIFT, NOINVERT
VK_RETURN, IDC_BUTTON_CUSTOM, VIRTKEY, SHIFT, CONTROL, NOINVERT
END
/////////////////////////////////////////////////////////////////////////////
//
// String Table
//
STRINGTABLE
BEGIN
IDS_NULLSOFT_BOOKMARKS "Nullsoft Bookmarks v%s"
65535 "{A3A1E7C0-761B-4391-A08A-F0D7AF38931C}"
END
STRINGTABLE
BEGIN
IDS_BOOKMARKS "Bookmarks"
IDS_ADD_TO_BOOKMARKS "Add to bookmarks"
IDS_BOOKMARK_TITLE "Bookmark Title"
IDS_BOOKMARK_FN_URL "Bookmark Filename/URL"
IDS_BROWSE_FOR_BM_ENTRY "Browse for bookmark entry..."
END
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
#include "version.rc2"
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED
@@ -0,0 +1,30 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29509.3
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ml_bookmarks", "ml_bookmarks.vcxproj", "{24335E73-2704-466A-8265-4314DD99886A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Release|Win32 = Release|Win32
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{24335E73-2704-466A-8265-4314DD99886A}.Debug|Win32.ActiveCfg = Debug|Win32
{24335E73-2704-466A-8265-4314DD99886A}.Debug|Win32.Build.0 = Debug|Win32
{24335E73-2704-466A-8265-4314DD99886A}.Debug|x64.ActiveCfg = Debug|x64
{24335E73-2704-466A-8265-4314DD99886A}.Debug|x64.Build.0 = Debug|x64
{24335E73-2704-466A-8265-4314DD99886A}.Release|Win32.ActiveCfg = Release|Win32
{24335E73-2704-466A-8265-4314DD99886A}.Release|Win32.Build.0 = Release|Win32
{24335E73-2704-466A-8265-4314DD99886A}.Release|x64.ActiveCfg = Release|x64
{24335E73-2704-466A-8265-4314DD99886A}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {91C2E933-BA43-4ADA-A8B4-B3A2E571BA11}
EndGlobalSection
EndGlobal
@@ -0,0 +1,317 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{24335E73-2704-466A-8265-4314DD99886A}</ProjectGuid>
<RootNamespace>ml_bookmarks</RootNamespace>
<WindowsTargetPlatformVersion>10.0.19041.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
<IncludePath>$(IncludePath)</IncludePath>
<LibraryPath>$(LibraryPath)</LibraryPath>
<EmbedManifest>true</EmbedManifest>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
<EmbedManifest>true</EmbedManifest>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
<IncludePath>$(IncludePath)</IncludePath>
<LibraryPath>$(LibraryPath)</LibraryPath>
<EmbedManifest>true</EmbedManifest>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
<EmbedManifest>true</EmbedManifest>
</PropertyGroup>
<PropertyGroup Label="Vcpkg">
<VcpkgEnableManifest>false</VcpkgEnableManifest>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<VcpkgInstalledDir>
</VcpkgInstalledDir>
<VcpkgUseStatic>false</VcpkgUseStatic>
<VcpkgConfiguration>Debug</VcpkgConfiguration>
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<VcpkgInstalledDir>
</VcpkgInstalledDir>
<VcpkgUseStatic>false</VcpkgUseStatic>
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<VcpkgInstalledDir>
</VcpkgInstalledDir>
<VcpkgUseStatic>false</VcpkgUseStatic>
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
<VcpkgConfiguration>Debug</VcpkgConfiguration>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<VcpkgInstalledDir>
</VcpkgInstalledDir>
<VcpkgUseStatic>false</VcpkgUseStatic>
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>.;..\..\..\Wasabi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;WIN32;_DEBUG;_WINDOWS;_USRDLL;ML_BOOKMARKS_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<BufferSecurityCheck>true</BufferSecurityCheck>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
</ClCompile>
<Link>
<AdditionalDependencies>comctl32.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
<SubSystem>Windows</SubSystem>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
<TargetMachine>MachineX86</TargetMachine>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<ModuleDefinitionFile>
</ModuleDefinitionFile>
</Link>
<PostBuildEvent>
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\
xcopy /Y /D $(IntDir)$(TargetName).pdb ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\ </Command>
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\'</Message>
</PostBuildEvent>
<ResourceCompile>
<PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
<Manifest>
<OutputManifestFile>$(IntDir)$(TargetName)$(TargetExt).intermediate.manifest</OutputManifestFile>
</Manifest>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>.;..\..\..\Wasabi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;WIN64;_DEBUG;_WINDOWS;_USRDLL;ML_BOOKMARKS_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<DisableSpecificWarnings>4302;4311;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<BufferSecurityCheck>true</BufferSecurityCheck>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
</ClCompile>
<Link>
<AdditionalDependencies>comctl32.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
<SubSystem>Windows</SubSystem>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
<PostBuildEvent>
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\
xcopy /Y /D $(IntDir)$(TargetName).pdb ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\ </Command>
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\'</Message>
</PostBuildEvent>
<ResourceCompile>
<PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
<Manifest>
<OutputManifestFile>$(IntDir)$(TargetName)$(TargetExt).intermediate.manifest</OutputManifestFile>
</Manifest>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<Optimization>MinSpace</Optimization>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<AdditionalIncludeDirectories>.;..\..\..\Wasabi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;WIN32;NDEBUG;_WINDOWS;_USRDLL;ML_BOOKMARKS_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>None</DebugInformationFormat>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
</ClCompile>
<Link>
<AdditionalDependencies>comctl32.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<GenerateDebugInformation>false</GenerateDebugInformation>
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
<SubSystem>Windows</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
<TargetMachine>MachineX86</TargetMachine>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<ModuleDefinitionFile>
</ModuleDefinitionFile>
</Link>
<PostBuildEvent>
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\ </Command>
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\'</Message>
</PostBuildEvent>
<ResourceCompile>
<PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
<Manifest>
<OutputManifestFile>$(IntDir)$(TargetName)$(TargetExt).intermediate.manifest</OutputManifestFile>
</Manifest>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<Optimization>MinSpace</Optimization>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<AdditionalIncludeDirectories>.;..\..\..\Wasabi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;WIN64;NDEBUG;_WINDOWS;_USRDLL;ML_BOOKMARKS_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>None</DebugInformationFormat>
<DisableSpecificWarnings>4302;4311;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
</ClCompile>
<Link>
<AdditionalDependencies>comctl32.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<GenerateDebugInformation>false</GenerateDebugInformation>
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
<SubSystem>Windows</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<ModuleDefinitionFile>
</ModuleDefinitionFile>
</Link>
<PostBuildEvent>
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\ </Command>
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\'</Message>
</PostBuildEvent>
<ResourceCompile>
<PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
<Manifest>
<OutputManifestFile>$(IntDir)$(TargetName)$(TargetExt).intermediate.manifest</OutputManifestFile>
</Manifest>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\General\gen_ml\config.cpp" />
<ClCompile Include="..\..\General\gen_ml\menu.cpp" />
<ClCompile Include="..\..\..\nu\DialogSkinner.cpp" />
<ClCompile Include="..\..\..\nu\listview.cpp" />
<ClCompile Include="..\..\..\nu\MediaLibraryInterface.cpp" />
<ClCompile Include="..\..\..\nu\menushortcuts.cpp" />
<ClCompile Include="bookmark.cpp" />
<ClCompile Include="main.cpp" />
<ClCompile Include="view.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\General\gen_ml\config.h" />
<ClInclude Include="..\..\General\gen_ml\menu.h" />
<ClInclude Include="..\..\..\nu\DialogSkinner.h" />
<ClInclude Include="..\..\..\nu\listview.h" />
<ClInclude Include="..\..\..\nu\MediaLibraryInterface.h" />
<ClInclude Include="..\..\..\nu\menushortcuts.h" />
<ClInclude Include="api__ml_bookmarks.h" />
<ClInclude Include="bookmark.h" />
<ClInclude Include="main.h" />
<ClInclude Include="resource.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="ml_bookmarks.rc" />
</ItemGroup>
<ItemGroup>
<Image Include="resources\ti_bookmarks_16x16x16.bmp" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\Wasabi\Wasabi.vcxproj">
<Project>{3e0bfa8a-b86a-42e9-a33f-ec294f823f7f}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
@@ -0,0 +1,100 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="view.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="bookmark.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\General\gen_ml\config.cpp">
<Filter>Source Files\gen_ml</Filter>
</ClCompile>
<ClCompile Include="..\..\..\nu\DialogSkinner.cpp">
<Filter>Source Files\nu</Filter>
</ClCompile>
<ClCompile Include="..\..\..\nu\listview.cpp">
<Filter>Source Files\nu</Filter>
</ClCompile>
<ClCompile Include="..\..\..\nu\MediaLibraryInterface.cpp">
<Filter>Source Files\nu</Filter>
</ClCompile>
<ClCompile Include="..\..\General\gen_ml\menu.cpp">
<Filter>Source Files\gen_ml</Filter>
</ClCompile>
<ClCompile Include="..\..\..\nu\menushortcuts.cpp">
<Filter>Source Files\nu</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="api__ml_bookmarks.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="bookmark.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="main.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="resource.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\General\gen_ml\config.h">
<Filter>Header Files\gen_ml</Filter>
</ClInclude>
<ClInclude Include="..\..\..\nu\DialogSkinner.h">
<Filter>Header Files\nu</Filter>
</ClInclude>
<ClInclude Include="..\..\..\nu\listview.h">
<Filter>Header Files\nu</Filter>
</ClInclude>
<ClInclude Include="..\..\..\nu\MediaLibraryInterface.h">
<Filter>Header Files\nu</Filter>
</ClInclude>
<ClInclude Include="..\..\General\gen_ml\menu.h">
<Filter>Header Files\gen_ml</Filter>
</ClInclude>
<ClInclude Include="..\..\..\nu\menushortcuts.h">
<Filter>Header Files\nu</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="Header Files">
<UniqueIdentifier>{b4c6c983-ad68-4d2d-a542-7f1bf6b1c155}</UniqueIdentifier>
</Filter>
<Filter Include="Ressource Files">
<UniqueIdentifier>{f072eba6-51ff-4c40-b136-bf3c79f3e120}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files">
<UniqueIdentifier>{b04fff17-1af4-4d74-b609-169c1a32b097}</UniqueIdentifier>
</Filter>
<Filter Include="Image Files">
<UniqueIdentifier>{56f5b459-ac0f-423d-b448-563135bf4bd8}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\gen_ml">
<UniqueIdentifier>{f4c07660-d9f0-42b1-8745-0d6446aef60f}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\nu">
<UniqueIdentifier>{d31d9efd-4434-46c5-8d2d-8a894aa24055}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\gen_ml">
<UniqueIdentifier>{00b097a1-1383-414f-8c19-82f97c6d06a5}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\nu">
<UniqueIdentifier>{8eaf67d8-c524-468a-a78b-334c69d1cf9e}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="ml_bookmarks.rc">
<Filter>Ressource Files</Filter>
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<Image Include="resources\ti_bookmarks_16x16x16.bmp">
<Filter>Image Files</Filter>
</Image>
</ItemGroup>
</Project>
@@ -0,0 +1,46 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by ml_bookmarks.rc
//
#define IDS_BOOKMARKS 1
#define IDS_ADD_TO_BOOKMARKS 2
#define IDS_BOOKMARK_TITLE 3
#define IDS_BOOKMARK_FN_URL 4
#define IDS_BROWSE_FOR_BM_ENTRY 5
#define IDR_MENU1 101
#define IDD_VIEW_BM 102
#define IDD_EDITBOOKMARK 103
#define IDC_CURSOR1 105
#define IDB_BITMAP1 106
#define IDR_VIEW_BM_ACCELERATORS 111
#define IDC_BUTTON_CUSTOM 1000
#define IDC_LIST 1001
#define IDC_BUTTON_PLAY 1002
#define IDC_BUTTON_ENQUEUE 1003
#define IDB_TREEITEM_BOOKMARKS 1003
#define IDC_EDITBOOK 1004
#define IDC_REMOVEBOOK 1005
#define IDC_TITLE 1006
#define IDC_FILE 1008
#define IDC_EDIT_FN 1009
#define ID_BMWND_PLAYSELECTEDFILES 40001
#define ID_BMWND_ENQUEUESELECTEDFILES 40002
#define ID_BMWND_REMOVESELECTEDBOOKMARKS 40003
#define ID_BMWND_EDITSELECTEDBOOKMARKS 40004
#define ID_BMWND_SELECTALL 40005
#define ID_Menu 40006
#define ID_BMWNDICON_HELP 40007
#define ID_BMWND_HELP 40008
#define ID_BMWND_SENDTO 40012
#define IDS_NULLSOFT_BOOKMARKS 65534
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 114
#define _APS_NEXT_COMMAND_VALUE 40013
#define _APS_NEXT_CONTROL_VALUE 1010
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
Binary file not shown.

After

Width:  |  Height:  |  Size: 568 B

@@ -0,0 +1,39 @@
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
#include "../../../Winamp/buildType.h"
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,27,0,0
PRODUCTVERSION WINAMP_PRODUCTVER
FILEFLAGSMASK 0x17L
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x4L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "Winamp SA"
VALUE "FileDescription", "Winamp Media Library Plug-in"
VALUE "FileVersion", "1,27,0,0"
VALUE "InternalName", "Nullsoft Bookmarks"
VALUE "LegalCopyright", "Copyright © 2003-2023 Winamp SA"
VALUE "LegalTrademarks", "Nullsoft and Winamp are trademarks of Winamp SA"
VALUE "OriginalFilename", "ml_bookmark.dll"
VALUE "ProductName", "Winamp"
VALUE "ProductVersion", STR_WINAMP_PRODUCTVER
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,276 @@
#include "main.h"
#include "./backBuffer.h"
BOOL
BackBuffer_Initialize(BackBuffer *self, HWND hwnd)
{
if (NULL == self)
return FALSE;
ZeroMemory(self, sizeof(BackBuffer));
self->hwnd = hwnd;
return TRUE;
}
void
BackBuffer_Uninitialize(BackBuffer *self)
{
BackBuffer_Reset(self);
}
void
BackBuffer_Reset(BackBuffer *self)
{
if (NULL == self)
return;
if (NULL != self->hdc)
{
if (NULL != self->previous)
SelectBitmap(self->hdc, self->previous);
DeleteDC(self->hdc);
}
if (NULL != self->bitmap)
{
DeleteObject(self->bitmap);
}
ZeroMemory(self, sizeof(BackBuffer));
}
BOOL
BackBuffer_EnsureSize(BackBuffer *self, long width, long height)
{
return BackBuffer_EnsureSizeEx(self, width, height, width, height);
}
BOOL
BackBuffer_EnsureSizeEx(BackBuffer *self, long width, long height, long allocWidth, long allocHeight)
{
BOOL result;
HDC windowDC;
HBITMAP bitmap;
long bitmapWidth, bitmapHeight;
if (NULL == self)
return FALSE;
if (width < 0)
width = 0;
if (height < 0)
height = 0;
if (NULL != self->bitmap)
{
BITMAP bitmapInfo;
if (sizeof(bitmapInfo) == GetObject(self->bitmap, sizeof(bitmapInfo), &bitmapInfo))
{
if (bitmapInfo.bmWidth >= width && bitmapInfo.bmHeight >= height)
return TRUE;
bitmapWidth = bitmapInfo.bmWidth;
bitmapHeight = bitmapInfo.bmHeight;
}
else
{
bitmapWidth = 0;
bitmapHeight = 0;
}
}
else
{
bitmapWidth = 0;
bitmapHeight = 0;
}
result = FALSE;
bitmap = NULL;
windowDC = GetDCEx(self->hwnd, NULL, DCX_CACHE | DCX_NORESETATTRS);
if(NULL != windowDC)
{
if (allocWidth < width)
allocWidth = width;
if (allocWidth < bitmapWidth)
allocWidth = bitmapWidth;
if (allocHeight < height)
allocHeight = height;
if (allocHeight < bitmapHeight)
allocHeight = bitmapHeight;
bitmap = CreateCompatibleBitmap(windowDC, allocWidth, allocHeight);
ReleaseDC(self->hwnd, windowDC);
}
if (NULL != bitmap)
{
if (NULL != self->hdc)
SelectBitmap(self->hdc, bitmap);
if (NULL != self->bitmap)
DeleteObject(self->bitmap);
self->bitmap = bitmap;
result = TRUE;
}
return result;
}
HDC
BackBuffer_GetDC(BackBuffer *self)
{
if (NULL == self)
return FALSE;
if (NULL == self->hdc)
{
HDC windowDC;
windowDC = GetDCEx(self->hwnd, NULL, DCX_CACHE | DCX_NORESETATTRS);
if (NULL != windowDC)
{
self->hdc = CreateCompatibleDC(windowDC);
ReleaseDC(self->hwnd, windowDC);
if (NULL != self->hdc)
{
if (NULL != self->bitmap)
self->previous = SelectBitmap(self->hdc, self->bitmap);
else
self->previous = GetCurrentBitmap(self->hdc);
}
}
}
return self->hdc;
}
BOOL
BackBuffer_Copy(BackBuffer *self, HDC hdc, long x, long y, long width, long height)
{
HDC sourceDC;
if (NULL == self || NULL == self->bitmap)
return FALSE;
sourceDC = BackBuffer_GetDC(self);
if (NULL == sourceDC)
return FALSE;
return BitBlt(hdc, x, y, width, height, sourceDC, 0, 0, SRCCOPY);
}
BOOL
BackBuffer_DrawTextEx(BackBuffer *self, HDC hdc, const wchar_t *string,
int length, RECT *rect, unsigned int format,
HFONT font, COLORREF backColor, COLORREF textColor, int backMode)
{
BOOL result = FALSE;
RECT bufferRect;
if (NULL == hdc || NULL == rect)
return FALSE;
SetRect(&bufferRect, 0, 0, RECTWIDTH(*rect), RECTHEIGHT(*rect));
if (NULL != self &&
FALSE != BackBuffer_EnsureSize(self, bufferRect.right, bufferRect.bottom))
{
HDC bufferDC = BackBuffer_GetDC(self);
if (NULL != bufferDC)
{
HFONT prevFont;
prevFont = SelectFont(bufferDC, font);
SetTextColor(bufferDC, textColor);
SetBkColor(bufferDC, backColor);
SetBkMode(bufferDC, backMode);
if (OPAQUE == backMode)
ExtTextOut(bufferDC, 0, 0, ETO_OPAQUE, &bufferRect, NULL, 0, NULL);
if (FALSE != DrawText(bufferDC, string, length, &bufferRect, format))
{
result = BackBuffer_Copy(self, hdc, rect->left, rect->top,
bufferRect.right, bufferRect.bottom);
}
SelectFont(bufferDC, prevFont);
}
}
if (FALSE == result)
{
HFONT prevFont;
COLORREF prevBackColor, prevTextColor;
int prevBkMode;
prevFont = SelectFont(hdc, font);
prevTextColor = SetTextColor(hdc, textColor);
prevBackColor = SetBkColor(hdc, backColor);
prevBkMode= SetBkMode(hdc, backMode);
result = DrawText(hdc, string, length, rect, format);
SelectFont(hdc, prevFont);
SetTextColor(hdc, prevTextColor);
SetBkColor(hdc, prevBackColor);
SetBkMode(hdc, prevBkMode);
}
return result;
}
BOOL
BackBuffer_DrawText(BackBuffer *self, HDC hdc, const wchar_t *string,
int length, RECT *rect, unsigned int format)
{
BOOL result = FALSE;
RECT bufferRect;
if (NULL == hdc || NULL == rect)
return FALSE;
SetRect(&bufferRect, 0, 0, RECTWIDTH(*rect), RECTHEIGHT(*rect));
if (NULL != self &&
FALSE != BackBuffer_EnsureSize(self, bufferRect.right, bufferRect.bottom))
{
HDC bufferDC = BackBuffer_GetDC(self);
if (NULL != bufferDC)
{
HFONT prevFont;
int backMode;
prevFont = SelectFont(bufferDC, GetCurrentFont(hdc));
SetTextColor(bufferDC, GetTextColor(hdc));
SetBkColor(bufferDC, GetBkColor(hdc));
backMode = GetBkMode(hdc);
SetBkMode(bufferDC, backMode);
if (OPAQUE == backMode)
ExtTextOut(bufferDC, 0, 0, ETO_OPAQUE, &bufferRect, NULL, 0, NULL);
if (FALSE != DrawText(bufferDC, string, length, &bufferRect, format))
{
result = BackBuffer_Copy(self, hdc, rect->left, rect->top,
bufferRect.right, bufferRect.bottom);
}
SelectFont(bufferDC, prevFont);
}
}
if (FALSE == result)
result = DrawText(hdc, string, length, rect, format);
return result;
}
@@ -0,0 +1,64 @@
#ifndef _NULLSOFT_WINAMP_ML_DEVICES_BACK_BUFFER_HEADER
#define _NULLSOFT_WINAMP_ML_DEVICES_BACK_BUFFER_HEADER
typedef struct BackBuffer
{
HBITMAP bitmap;
HWND hwnd;
HDC hdc;
HBITMAP previous;
} BackBuffer;
BOOL
BackBuffer_Initialize(BackBuffer *self, HWND hwnd);
void
BackBuffer_Uninitialize(BackBuffer *self);
BOOL
BackBuffer_EnsureSize(BackBuffer *self,
long width,
long height);
BOOL
BackBuffer_EnsureSizeEx(BackBuffer *self,
long width,
long height,
long allocWidth,
long allocHeight);
HDC
BackBuffer_GetDC(BackBuffer *self);
BOOL
BackBuffer_Copy(BackBuffer *self,
HDC hdc,
long x,
long y,
long width,
long height);
void
BackBuffer_Reset(BackBuffer *self);
BOOL
BackBuffer_DrawText(BackBuffer *self,
HDC hdc,
const wchar_t *string,
int length,
RECT *rect,
unsigned int format);
BOOL
BackBuffer_DrawTextEx(BackBuffer *self,
HDC hdc,
const wchar_t *string,
int length,
RECT *rect,
unsigned int format,
HFONT font,
COLORREF backColor,
COLORREF textColor,
int backMode);
#endif //_NULLSOFT_WINAMP_ML_DEVICES_BACK_BUFFER_HEADER
+76
View File
@@ -0,0 +1,76 @@
#ifndef _NULLSOFT_WINAMP_ML_DEVICES_COMMON_HEADER
#define _NULLSOFT_WINAMP_ML_DEVICES_COMMON_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#ifndef LONGX86
#ifdef _WIN64
#define LONGX86 LONG_PTR
#else /*_WIN64*/
#define LONGX86 LONG
#endif /*_WIN64*/
#endif // LONGX86
#define CSTR_INVARIANT MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT)
#ifdef __cplusplus
#define SENDMSG(__hwnd, __msgId, __wParam, __lParam) ::SendMessageW((__hwnd), (__msgId), (__wParam), (__lParam))
#else
#define SENDMSG(__hwnd, __msgId, __wParam, __lParam) SendMessageW((__hwnd), (__msgId), (__wParam), (__lParam))
#endif // __cplusplus
#define SENDMLIPC(__hwndML, __ipcMsgId, __param) SENDMSG((__hwndML), WM_ML_IPC, (WPARAM)(__param), (LPARAM)(__ipcMsgId))
#define SENDWAIPC(__hwndWA, __ipcMsgId, __param) SENDMSG((__hwndWA), WM_WA_IPC, (WPARAM)(__param), (LPARAM)(__ipcMsgId))
#define SENDCMD(__hwnd, __ctrlId, __eventId, __hctrl) (SENDMSG((__hwnd), WM_COMMAND, MAKEWPARAM(__ctrlId, __eventId), (LPARAM)(__hctrl)))
#define DIALOG_RESULT(__hwnd, __result) { SetWindowLongPtrW((__hwnd), DWLP_MSGRESULT, ((LONGX86)(LONG_PTR)(__result))); return TRUE; }
#ifndef GetWindowStyle
#define GetWindowStyle(__hwnd) ((UINT)GetWindowLongPtr((__hwnd), GWL_STYLE))
#endif //GetWindowStyle
#ifndef SetWindowStyle
#define SetWindowStyle(__hwnd, __style) (SetWindowLongPtr((__hwnd), GWL_STYLE, (__style)))
#endif //SetWindowStyle
#ifndef GetWindowStyleEx
#define GetWindowStyleEx(__hwnd) ((UINT)GetWindowLongPtr((__hwnd), GWL_EXSTYLE))
#endif // GetWindowStyleEx
#ifndef SetWindowStyleEx
#define SetWindowStyleEx(__hwnd, __style) (SetWindowLongPtr((__hwnd), GWL_EXSTYLE, (__style)))
#endif //SetWindowStyle
#ifndef RECTWIDTH
#define RECTWIDTH(__r) ((__r).right - (__r).left)
#endif
#ifndef RECTHEIGHT
#define RECTHEIGHT(__r) ((__r).bottom - (__r).top)
#endif
#undef CLAMP
#define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)))
#ifndef ARRAYSIZE
#define ARRAYSIZE(_a) (sizeof(_a)/sizeof((_a)[0]))
#endif
#ifndef ABS
#define ABS(x) (((x) > 0) ? (x) : (-x))
#endif
#ifndef MIN
#define MIN(v1, v2) (((v1) < (v2)) ? (v1) : (v2))
#endif
#ifndef MAX
#define MAX(v1, v2) (((v1) > (v2)) ? (v1) : (v2))
#endif
#endif //_NULLSOFT_WINAMP_ML_DEVICES_COMMON_HEADER
+119
View File
@@ -0,0 +1,119 @@
#include "main.h"
#include "./config.h"
#include <strsafe.h>
#define CONFIG_SUFFIX L"Plugins\\ml"
#define CONFIG_FILE L"ml_devices.ini"
static const char *
Config_GetPath(BOOL ensureExist)
{
static const char *configPath = NULL;
if (NULL == configPath)
{
const wchar_t *userPath;
wchar_t buffer[MAX_PATH * 2] = {0};
if (NULL == WASABI_API_APP)
return NULL;
userPath = WASABI_API_APP->path_getUserSettingsPath();
if (NULL == userPath)
return NULL;
if (0 != PathCombine(buffer, userPath, CONFIG_SUFFIX))
{
if ((FALSE == ensureExist || SUCCEEDED(Plugin_EnsurePathExist(buffer))) &&
FALSE != PathAppend(buffer,CONFIG_FILE))
{
configPath = String_ToAnsi(CP_UTF8, 0, buffer, -1, NULL, NULL);
}
}
}
return configPath;
}
unsigned long
Config_ReadString(const char *section, const char *key, const char *defaultValue, char *returnedString, unsigned long size)
{
return GetPrivateProfileStringA(section, key, defaultValue, returnedString, size, Config_GetPath(FALSE));
}
unsigned int
Config_ReadInt(const char *section, const char *key, int defaultValue)
{
return GetPrivateProfileIntA(section, key, defaultValue, Config_GetPath(FALSE));
}
BOOL
Config_ReadBool(const char *section, const char *key, BOOL defaultValue)
{
char buffer[32] = {0};
int length = Config_ReadString(section, key, NULL, buffer, ARRAYSIZE(buffer));
if (0 == length)
return defaultValue;
if (1 == length)
{
switch(*buffer)
{
case '0':
case 'n':
case 'f':
return FALSE;
case '1':
case 'y':
case 't':
return TRUE;
}
}
else
{
if (CSTR_EQUAL == CompareStringA(CSTR_INVARIANT, NORM_IGNORECASE, "yes", -1, buffer, length) ||
CSTR_EQUAL == CompareStringA(CSTR_INVARIANT, NORM_IGNORECASE, "true", -1, buffer, length))
{
return TRUE;
}
if (CSTR_EQUAL == CompareStringA(CSTR_INVARIANT, NORM_IGNORECASE, "no", -1, buffer, length) ||
CSTR_EQUAL == CompareStringA(CSTR_INVARIANT, NORM_IGNORECASE, "false", -1, buffer, length))
{
return FALSE;
}
}
if (FALSE != StrToIntExA(buffer, STIF_SUPPORT_HEX, &length))
return (0 != length);
return defaultValue;
}
BOOL
Config_WriteString(const char *section, const char *key, const char *value)
{
const char *configPath = Config_GetPath(TRUE);
if (NULL == configPath || '\0' == *configPath)
return FALSE;
return (0 != WritePrivateProfileStringA(section, key, value, configPath));
}
BOOL
Config_WriteInt(const char *section, const char *key, int value)
{
char buffer[32] = {0};
if (FAILED(StringCchPrintfA(buffer, ARRAYSIZE(buffer), "%d", value)))
return FALSE;
return Config_WriteString(section, key, buffer);
}
BOOL
Config_WriteBool(const char *section, const char *key, BOOL value)
{
return Config_WriteString(section, key, (FALSE != value) ? "yes" : "no");
}
+44
View File
@@ -0,0 +1,44 @@
#ifndef _NULLSOFT_WINAMP_ML_DEVICES_CONFIG_HEADER
#define _NULLSOFT_WINAMP_ML_DEVICES_CONFIG_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
unsigned long
Config_ReadString(const char *section,
const char *key,
const char *defaultValue,
char *returnedStrign,
unsigned long size);
unsigned int
Config_ReadInt(const char *section,
const char *key,
int defaultValue);
BOOL
Config_ReadBool(const char *section,
const char *key,
BOOL defaultValue);
BOOL
Config_WriteString(const char *section,
const char *key,
const char *value);
BOOL
Config_WriteInt(const char *section,
const char *key,
int value);
BOOL
Config_WriteBool(const char *section,
const char *key,
BOOL value);
#endif // _NULLSOFT_WINAMP_ML_DEVICES_CONFIG_HEADER
@@ -0,0 +1,207 @@
#include "main.h"
#include "deviceCommands.h"
typedef struct DeviceCommandInfo
{
const char *name;
unsigned int title;
unsigned int description;
unsigned int smallIcon;
unsigned int largeIcon;
} DeviceCommandInfo;
static DeviceCommandInfo registeredCommands[] =
{
{ "sync",
IDS_SYNC_COMMAND_TITLE,
IDS_SYNC_COMMAND_DESC,
IDR_SYNC_COMMAND_SMALL_IMAGE,
IDR_SYNC_COMMAND_LARGE_IMAGE },
{ "cancel_sync",
IDS_CANCEL_SYNC_COMMAND_TITLE,
IDS_CANCEL_SYNC_COMMAND_DESC,
IDR_CANCEL_SYNC_COMMAND_SMALL_IMAGE,
IDR_CANCEL_SYNC_COMMAND_LARGE_IMAGE },
{ "attach",
IDS_ATTACH_COMMAND_TITLE,
IDS_ATTACH_COMMAND_DESC,
IDR_ATTACH_COMMAND_SMALL_IMAGE,
IDR_ATTACH_COMMAND_LARGE_IMAGE },
{ "detach",
IDS_DETACH_COMMAND_TITLE,
IDS_DETACH_COMMAND_DESC,
IDR_DETACH_COMMAND_SMALL_IMAGE,
IDR_DETACH_COMMAND_LARGE_IMAGE },
{ "eject",
IDS_EJECT_COMMAND_TITLE,
IDS_EJECT_COMMAND_DESC,
IDR_EJECT_COMMAND_SMALL_IMAGE,
IDR_EJECT_COMMAND_LARGE_IMAGE },
{ "rename",
IDS_RENAME_COMMAND_TITLE,
IDS_RENAME_COMMAND_DESC,
IDR_RENAME_COMMAND_SMALL_IMAGE,
IDR_RENAME_COMMAND_LARGE_IMAGE },
{ "view_open",
IDS_VIEW_OPEN_COMMAND_TITLE,
IDS_VIEW_OPEN_COMMAND_DESC,
IDR_VIEW_OPEN_COMMAND_SMALL_IMAGE,
IDR_VIEW_OPEN_COMMAND_LARGE_IMAGE },
{ "preferences",
IDS_PREFERENCES_COMMAND_TITLE,
IDS_PREFERENCES_COMMAND_DESC,
IDR_PREFERENCES_COMMAND_SMALL_IMAGE,
IDR_PREFERENCES_COMMAND_LARGE_IMAGE },
{ "playlist_create",
IDS_PLAYLIST_CREATE_COMMAND_TITLE,
IDS_PLAYLIST_CREATE_COMMAND_DESC,
IDR_PLAYLIST_CREATE_COMMAND_SMALL_IMAGE,
IDR_PLAYLIST_CREATE_COMMAND_LARGE_IMAGE },
};
static ifc_devicecommand * _cdecl
DeviceCommands_RegisterCommandCb(const char *name, void *user)
{
size_t index;
wchar_t buffer[2048] = {0};
DeviceCommandInfo *commandInfo;
ifc_devicecommand *command;
ifc_devicecommandeditor *editor;
commandInfo = NULL;
for(index = 0; index < ARRAYSIZE(registeredCommands); index++)
{
if (name == registeredCommands[index].name)
{
commandInfo = &registeredCommands[index];
break;
}
}
if (NULL == commandInfo)
return NULL;
if (NULL == WASABI_API_DEVICES)
return NULL;
if (FAILED(WASABI_API_DEVICES->CreateCommand(commandInfo->name, &command)))
return NULL;
if (FAILED(command->QueryInterface(IFC_DeviceCommandEditor, (void**)&editor)))
{
command->Release();
return NULL;
}
if (0 != commandInfo->title)
{
WASABI_API_LNGSTRINGW_BUF(commandInfo->title, buffer, ARRAYSIZE(buffer));
editor->SetDisplayName(buffer);
}
if (0 != commandInfo->description)
{
WASABI_API_LNGSTRINGW_BUF(commandInfo->description, buffer, ARRAYSIZE(buffer));
editor->SetDescription(buffer);
}
if (0 != commandInfo->smallIcon || 0 != commandInfo->largeIcon)
{
ifc_deviceiconstore *iconStore;
if (SUCCEEDED(editor->GetIconStore(&iconStore)))
{
if (0 != commandInfo->smallIcon)
{
if (FALSE != Plugin_GetResourceString(MAKEINTRESOURCE(commandInfo->smallIcon), RT_RCDATA, buffer, ARRAYSIZE(buffer)))
iconStore->Add(buffer, 16, 16, TRUE);
}
if (0 != commandInfo->largeIcon)
{
if (FALSE != Plugin_GetResourceString(MAKEINTRESOURCE(commandInfo->largeIcon), RT_RCDATA, buffer, ARRAYSIZE(buffer)))
iconStore->Add(buffer, 43, 24, TRUE);
}
iconStore->Release();
}
}
editor->Release();
return command;
}
BOOL
DeviceCommands_Register()
{
const char *commands[ARRAYSIZE(registeredCommands)];
size_t index;
if (NULL == WASABI_API_DEVICES)
return FALSE;
for(index = 0; index < ARRAYSIZE(commands); index++)
{
commands[index] = registeredCommands[index].name;
}
WASABI_API_DEVICES->CommandRegisterIndirect(commands, ARRAYSIZE(commands), DeviceCommands_RegisterCommandCb, NULL);
return TRUE;
}
BOOL
DeviceCommand_GetSupported(ifc_device *device, const char *name, DeviceCommandContext context,
ifc_devicesupportedcommand **commandOut)
{
ifc_devicesupportedcommandenum *enumerator;
ifc_devicesupportedcommand *command;
BOOL foundCommand;
if (NULL == device ||
NULL == name ||
FAILED(device->EnumerateCommands(&enumerator, context)))
{
return FALSE;
}
foundCommand = FALSE;
while (S_OK == enumerator->Next(&command, 1, NULL))
{
if (CSTR_EQUAL == CompareStringA(CSTR_INVARIANT, 0, name, -1, command->GetName(), -1))
{
foundCommand = TRUE;
if (NULL != commandOut)
*commandOut = command;
else
command->Release();
break;
}
command->Release();
}
enumerator->Release();
return foundCommand;
}
BOOL
DeviceCommand_GetEnabled(ifc_device *device, const char *name, DeviceCommandContext context)
{
ifc_devicesupportedcommand *command;
DeviceCommandFlags flags;
if (FALSE == DeviceCommand_GetSupported(device, name, context, &command))
return FALSE;
if (FAILED(command->GetFlags(&flags)))
flags = DeviceCommandFlag_Disabled;
command->Release();
return (0 == (DeviceCommandFlag_Disabled & flags));
}
@@ -0,0 +1,24 @@
#ifndef _NULLSOFT_WINAMP_ML_DEVICES_DEVICE_COMMANDS_HEADER
#define _NULLSOFT_WINAMP_ML_DEVICES_DEVICE_COMMANDS_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
BOOL
DeviceCommands_Register();
BOOL
DeviceCommand_GetSupported(ifc_device *device,
const char *name,
DeviceCommandContext context,
ifc_devicesupportedcommand **commandOut);
BOOL
DeviceCommand_GetEnabled(ifc_device *device,
const char *name,
DeviceCommandContext context);
#endif //_NULLSOFT_WINAMP_ML_DEVICES_DEVICE_COMMANDS_HEADER
@@ -0,0 +1,206 @@
#include "main.h"
#include "./deviceHandler.h"
DeviceHandler::DeviceHandler()
: ref(1), relayWindow(NULL)
{
}
DeviceHandler::~DeviceHandler()
{
}
HRESULT DeviceHandler::CreateInstance(DeviceHandler **instance)
{
if (NULL == instance)
return E_POINTER;
*instance = new DeviceHandler();
if (NULL == *instance)
return E_OUTOFMEMORY;
return S_OK;
}
size_t DeviceHandler::AddRef()
{
return InterlockedIncrement((LONG*)&ref);
}
size_t DeviceHandler::Release()
{
if (0 == ref)
return ref;
LONG r = InterlockedDecrement((LONG*)&ref);
if (0 == r)
delete(this);
return r;
}
int DeviceHandler::QueryInterface(GUID interface_guid, void **object)
{
if (NULL == object) return E_POINTER;
if (IsEqualIID(interface_guid, IFC_DeviceEvent))
*object = static_cast<ifc_deviceevent*>(this);
else
{
*object = NULL;
return E_NOINTERFACE;
}
if (NULL == *object)
return E_UNEXPECTED;
AddRef();
return S_OK;
}
void DeviceHandler::IconChanged(ifc_device *device)
{
if (NULL != relayWindow)
EVENTRELAY_NOTIFY_DEVICE(relayWindow, device, Event_DeviceIconChanged);
}
void DeviceHandler::DisplayNameChanged(ifc_device *device, const wchar_t *displayName)
{
if (NULL != relayWindow)
EVENTRELAY_NOTIFY_DEVICE(relayWindow, device, Event_DeviceDisplayNameChanged);
}
void DeviceHandler::AttachmentChanged(ifc_device *device, BOOL attached)
{
if (NULL != relayWindow)
{
if (FALSE != attached)
{
EVENTRELAY_NOTIFY_DEVICE(relayWindow, device, Event_DeviceAttached);
}
else
{
EVENTRELAY_NOTIFY_DEVICE(relayWindow, device, Event_DeviceDetached);
}
}
}
void DeviceHandler::VisibilityChanged(ifc_device *device, BOOL visible)
{
if (NULL != relayWindow)
{
if (FALSE == visible)
{
EVENTRELAY_NOTIFY_DEVICE(relayWindow, device, Event_DeviceHidden);
}
else
{
EVENTRELAY_NOTIFY_DEVICE(relayWindow, device, Event_DeviceShown);
}
}
}
void DeviceHandler::TotalSpaceChanged(ifc_device *device, size_t space)
{
if (NULL != relayWindow)
EVENTRELAY_NOTIFY_DEVICE(relayWindow, device, Event_DeviceTotalSpaceChanged);
}
void DeviceHandler::UsedSpaceChanged(ifc_device *device, size_t space)
{
if (NULL != relayWindow)
EVENTRELAY_NOTIFY_DEVICE(relayWindow, device, Event_DeviceUsedSpaceChanged);
}
void DeviceHandler::CommandChanged(ifc_device *device)
{
if (NULL != relayWindow)
EVENTRELAY_NOTIFY_DEVICE(relayWindow, device, Event_DeviceCommandChanged);
}
void DeviceHandler::ActivityStarted(ifc_device *device, ifc_deviceactivity *activity)
{
if (NULL != relayWindow)
EVENTRELAY_NOTIFY_DEVICE(relayWindow, device, Event_DeviceActivityStarted);
}
void DeviceHandler::ActivityFinished(ifc_device *device, ifc_deviceactivity *activity)
{
if (NULL != relayWindow)
EVENTRELAY_NOTIFY_DEVICE(relayWindow, device, Event_DeviceActivityFinished);
}
void DeviceHandler::ActivityChanged(ifc_device *device, ifc_deviceactivity *activity)
{
if (NULL != relayWindow)
EVENTRELAY_NOTIFY_DEVICE(relayWindow, device, Event_DeviceActivityChanged);
}
void DeviceHandler::ModelChanged(ifc_device *device, const wchar_t *model)
{
if (NULL != relayWindow)
EVENTRELAY_NOTIFY_DEVICE(relayWindow, device, Event_DeviceModelChanged);
}
void DeviceHandler::StatusChanged(ifc_device *device, const wchar_t *status)
{
if (NULL != relayWindow)
EVENTRELAY_NOTIFY_DEVICE(relayWindow, device, Event_DeviceStatusChanged);
}
HRESULT DeviceHandler::SetRelayWindow(HWND hwnd)
{
relayWindow = hwnd;
return S_OK;
}
HRESULT DeviceHandler::Advise(ifc_device *device)
{
HRESULT hr;
if (NULL == device)
return E_INVALIDARG;
hr = device->Advise(this);
if (FAILED(hr))
return hr;
return hr;
}
HRESULT DeviceHandler::Unadvise(ifc_device *device)
{
HRESULT hr;
if (NULL == device)
return E_INVALIDARG;
hr = device->Unadvise(this);
if (FAILED(hr))
return hr;
return hr;
}
#define CBCLASS DeviceHandler
START_DISPATCH;
CB(ADDREF, AddRef)
CB(RELEASE, Release)
CB(QUERYINTERFACE, QueryInterface)
VCB(API_ICONCHANGED, IconChanged)
VCB(API_DISPLAYNAMECHANGED, DisplayNameChanged)
VCB(API_ATTACHMENTCHANGED, AttachmentChanged)
VCB(API_VISIBILITYCHANGED, VisibilityChanged)
VCB(API_TOTALSPACECHANGED, TotalSpaceChanged)
VCB(API_USEDSPACECHANGED, UsedSpaceChanged)
VCB(API_COMMANDCHANGED, CommandChanged)
VCB(API_ACTIVITYSTARTED, ActivityStarted)
VCB(API_ACTIVITYFINISHED, ActivityFinished)
VCB(API_ACTIVITYCHANGED, ActivityChanged)
VCB(API_MODELCHANGED, ModelChanged)
VCB(API_STATUSCHANGED, StatusChanged)
END_DISPATCH;
#undef CBCLASS
@@ -0,0 +1,56 @@
#ifndef _NULLSOFT_WINAMP_ML_DEVICES_DEVICE_HANDLER_HEADER
#define _NULLSOFT_WINAMP_ML_DEVICES_DEVICE_HANDLER_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
#include "../devices/ifc_deviceevent.h"
class DeviceHandler: public ifc_deviceevent
{
protected:
DeviceHandler();
~DeviceHandler();
public:
static HRESULT CreateInstance(DeviceHandler **instance);
public:
/* Dispatchable */
size_t AddRef();
size_t Release();
int QueryInterface(GUID interface_guid, void **object);
/* ifc_deviceevent */
void IconChanged(ifc_device *device);
void DisplayNameChanged(ifc_device *device, const wchar_t *displayName);
void AttachmentChanged(ifc_device *device, BOOL attached);
void VisibilityChanged(ifc_device *device, BOOL visible);
void TotalSpaceChanged(ifc_device *device, size_t space);
void UsedSpaceChanged(ifc_device *device, size_t space);
void CommandChanged(ifc_device *device);
void ActivityStarted(ifc_device *device, ifc_deviceactivity *activity);
void ActivityFinished(ifc_device *device, ifc_deviceactivity *activity);
void ActivityChanged(ifc_device *device, ifc_deviceactivity *activity);
void ModelChanged(ifc_device *device, const wchar_t *model);
void StatusChanged(ifc_device *device, const wchar_t *status);
public:
HRESULT SetRelayWindow(HWND hwnd);
HRESULT Advise(ifc_device *device);
HRESULT Unadvise(ifc_device *device);
protected:
size_t ref;
HWND relayWindow;
protected:
RECVS_DISPATCH;
};
#endif //_NULLSOFT_WINAMP_ML_DEVICES_DEVICE_HANDLER_HEADER
@@ -0,0 +1,174 @@
#include "main.h"
#include "./deviceManagerHandler.h"
DeviceManagerHandler::DeviceManagerHandler()
: ref(1), relayWindow(NULL)
{
}
DeviceManagerHandler::~DeviceManagerHandler()
{
}
HRESULT DeviceManagerHandler::CreateInstance(DeviceManagerHandler **instance)
{
if (NULL == instance)
return E_POINTER;
*instance = new DeviceManagerHandler();
if (NULL == *instance)
return E_OUTOFMEMORY;
return S_OK;
}
size_t DeviceManagerHandler::AddRef()
{
return InterlockedIncrement((LONG*)&ref);
}
size_t DeviceManagerHandler::Release()
{
if (0 == ref)
return ref;
LONG r = InterlockedDecrement((LONG*)&ref);
if (0 == r)
delete(this);
return r;
}
int DeviceManagerHandler::QueryInterface(GUID interface_guid, void **object)
{
if (NULL == object) return E_POINTER;
if (IsEqualIID(interface_guid, IFC_DeviceManagerEvent))
*object = static_cast<ifc_devicemanagerevent*>(this);
else
{
*object = NULL;
return E_NOINTERFACE;
}
if (NULL == *object)
return E_UNEXPECTED;
AddRef();
return S_OK;
}
void DeviceManagerHandler::TypeAdded(api_devicemanager *manager, ifc_devicetype *type)
{
if (NULL != relayWindow)
EVENTRELAY_NOTIFY_TYPE(relayWindow, type, Event_TypeRegistered);
}
void DeviceManagerHandler::TypeRemoved(api_devicemanager *manager, ifc_devicetype *type)
{
if (NULL != relayWindow)
EVENTRELAY_NOTIFY_TYPE(relayWindow, type, Event_TypeUnregistered);
}
void DeviceManagerHandler::ConnectionAdded(api_devicemanager *manager, ifc_deviceconnection *connection)
{
if (NULL != relayWindow)
EVENTRELAY_NOTIFY_CONNECTION(relayWindow, connection, Event_ConnectionRegistered);
}
void DeviceManagerHandler::ConnectionRemoved(api_devicemanager *manager, ifc_deviceconnection *connection)
{
if (NULL != relayWindow)
EVENTRELAY_NOTIFY_CONNECTION(relayWindow, connection, Event_ConnectionUnregistered);
}
void DeviceManagerHandler::CommandAdded(api_devicemanager *manager, ifc_devicecommand *command)
{
if (NULL != relayWindow)
EVENTRELAY_NOTIFY_COMMAND(relayWindow, command, Event_CommandRegistered);
}
void DeviceManagerHandler::CommandRemoved(api_devicemanager *manager, ifc_devicecommand *command)
{
if (NULL != relayWindow)
EVENTRELAY_NOTIFY_COMMAND(relayWindow, command, Event_CommandUnregistered);
}
void DeviceManagerHandler::DeviceAdded(api_devicemanager *manager, ifc_device *device)
{
if (NULL != relayWindow)
EVENTRELAY_NOTIFY_DEVICE(relayWindow, device, Event_DeviceAdded);
}
void DeviceManagerHandler::DeviceRemoved(api_devicemanager *manager, ifc_device *device)
{
if (NULL != relayWindow)
EVENTRELAY_NOTIFY_DEVICE(relayWindow, device, Event_DeviceRemoved);
}
void DeviceManagerHandler::DiscoveryStarted(api_devicemanager *manager)
{
if (NULL != relayWindow)
EVENTRELAY_NOTIFY_DISCOVERY(relayWindow, manager, Event_DiscoveryStarted);
}
void DeviceManagerHandler::DiscoveryFinished(api_devicemanager *manager)
{
if (NULL != relayWindow)
EVENTRELAY_NOTIFY_DISCOVERY(relayWindow, manager, Event_DiscoveryFinished);
}
HRESULT DeviceManagerHandler::SetRelayWindow(HWND hwnd)
{
relayWindow = hwnd;
return S_OK;
}
HRESULT DeviceManagerHandler::Advise(api_devicemanager *manager)
{
HRESULT hr;
if (NULL == manager)
return E_INVALIDARG;
hr = manager->Advise(this);
if (FAILED(hr))
return hr;
return hr;
}
HRESULT DeviceManagerHandler::Unadvise(api_devicemanager *manager)
{
HRESULT hr;
if (NULL == manager)
return E_INVALIDARG;
hr = manager->Unadvise(this);
if (FAILED(hr))
return hr;
return hr;
}
#define CBCLASS DeviceManagerHandler
START_DISPATCH;
CB(ADDREF, AddRef)
CB(RELEASE, Release)
CB(QUERYINTERFACE, QueryInterface)
VCB(API_TYPEADDED, TypeAdded)
VCB(API_TYPEREMOVED, TypeRemoved)
VCB(API_CONNECTIONADDED, ConnectionAdded)
VCB(API_CONNECTIONREMOVED, ConnectionRemoved)
VCB(API_COMMANDADDED, CommandAdded)
VCB(API_COMMANDREMOVED, CommandRemoved)
VCB(API_DEVICEADDED, DeviceAdded)
VCB(API_DEVICEREMOVED, DeviceRemoved)
VCB(API_DISCOVERYSTARTED, DiscoveryStarted)
VCB(API_DISCOVERYFINISHED, DiscoveryFinished)
END_DISPATCH;
#undef CBCLASS
@@ -0,0 +1,54 @@
#ifndef _NULLSOFT_WINAMP_ML_DEVICES_DEVICE_MANAGER_HANDLER_HEADER
#define _NULLSOFT_WINAMP_ML_DEVICES_DEVICE_MANAGER_HANDLER_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
#include "../devices/api_devicemanager.h"
//#include <ifc_devicemanagerevent.h>
class DeviceManagerHandler: public ifc_devicemanagerevent
{
protected:
DeviceManagerHandler();
~DeviceManagerHandler();
public:
static HRESULT CreateInstance(DeviceManagerHandler **instance);
public:
/* Dispatchable */
size_t AddRef();
size_t Release();
int QueryInterface(GUID interface_guid, void **object);
/* ifc_devicemanagerevent */
void TypeAdded(api_devicemanager *manager, ifc_devicetype *type);
void TypeRemoved(api_devicemanager *manager, ifc_devicetype *type);
void ConnectionAdded(api_devicemanager *manager, ifc_deviceconnection *connection);
void ConnectionRemoved(api_devicemanager *manager, ifc_deviceconnection *connection);
void CommandAdded(api_devicemanager *manager, ifc_devicecommand *command);
void CommandRemoved(api_devicemanager *manager, ifc_devicecommand *command);
void DeviceAdded(api_devicemanager *manager, ifc_device *device);
void DeviceRemoved(api_devicemanager *manager, ifc_device *device);
void DiscoveryStarted(api_devicemanager *manager);
void DiscoveryFinished(api_devicemanager *manager);
public:
HRESULT SetRelayWindow(HWND hwnd);
HRESULT Advise(api_devicemanager *manager);
HRESULT Unadvise(api_devicemanager *manager);
protected:
size_t ref;
HWND relayWindow;
protected:
RECVS_DISPATCH;
};
#endif //_NULLSOFT_WINAMP_ML_DEVICES_DEVICE_MANAGER_HANDLER_HEADER
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,79 @@
#ifndef _NULLSOFT_WINAMP_ML_DEVICES_EMBEDED_EDITOR_HEADER
#define _NULLSOFT_WINAMP_ML_DEVICES_EMBEDED_EDITOR_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
typedef void (CALLBACK *EmbeddedEditorFinishCb)(HWND /*editorWindow*/, BOOL /*canceled*/,
const wchar_t * /*text*/, void * /*user*/);
BOOL
EmbeddedEditor_Attach(HWND hwnd,
EmbeddedEditorFinishCb callback,
void *user);
BOOL
EmbeddedEditor_AdjustWindowRectEx(RECT *rect,
unsigned long styleEx,
unsigned long style);
#define EMBEDDEDEDITOR_WM_FIRST (WM_USER + 10)
#define EMBEDDEDEDITOR_WM_SET_TEXT_COLOR (EMBEDDEDEDITOR_WM_FIRST + 0)
#define EMBEDDEDEDITOR_SET_TEXT_COLOR(/*HWND*/ _hwnd, /*COLORREF*/ _color)\
((COLORREF)SendMessageW((_hwnd), EMBEDDEDEDITOR_WM_SET_TEXT_COLOR, 0, (LPARAM)(_color)))
#define EMBEDDEDEDITOR_WM_GET_TEXT_COLOR (EMBEDDEDEDITOR_WM_FIRST + 1)
#define EMBEDDEDEDITOR_GET_TEXT_COLOR(/*HWND*/ _hwnd)\
((COLORREF)SendMessageW((_hwnd), EMBEDDEDEDITOR_WM_GET_TEXT_COLOR, 0, 0L))
#define EMBEDDEDEDITOR_WM_SET_BACK_COLOR (EMBEDDEDEDITOR_WM_FIRST + 2)
#define EMBEDDEDEDITOR_SET_BACK_COLOR(/*HWND*/ _hwnd, /*COLORREF*/ _color)\
((COLORREF)SendMessageW((_hwnd), EMBEDDEDEDITOR_WM_SET_BACK_COLOR, 0, (LPARAM)(_color)))
#define EMBEDDEDEDITOR_WM_GET_BACK_COLOR (EMBEDDEDEDITOR_WM_FIRST + 3)
#define EMBEDDEDEDITOR_GET_BACK_COLOR(/*HWND*/ _hwnd)\
((COLORREF)SendMessageW((_hwnd), EMBEDDEDEDITOR_WM_GET_BACK_COLOR, 0, 0L))
#define EMBEDDEDEDITOR_WM_SET_BORDER_COLOR (EMBEDDEDEDITOR_WM_FIRST + 4)
#define EMBEDDEDEDITOR_SET_BORDER_COLOR(/*HWND*/ _hwnd, /*COLORREF*/ _color)\
((COLORREF)SendMessageW((_hwnd), EMBEDDEDEDITOR_WM_SET_BORDER_COLOR, 0, (LPARAM)(_color)))
#define EMBEDDEDEDITOR_WM_GET_BORDER_COLOR (EMBEDDEDEDITOR_WM_FIRST + 5)
#define EMBEDDEDEDITOR_GET_BORDER_COLOR(/*HWND*/ _hwnd)\
((COLORREF)SendMessageW((_hwnd), EMBEDDEDEDITOR_WM_GET_BORDER_COLOR, 0, 0L))
#define EMBEDDEDEDITOR_WM_SET_USER_DATA (EMBEDDEDEDITOR_WM_FIRST + 6)
#define EMBEDDEDEDITOR_SET_USER_DATA(/*HWND*/ _hwnd, /*void* */ _user)\
((void*)SendMessageW((_hwnd), EMBEDDEDEDITOR_WM_SET_USER_DATA, 0, (LPARAM)(_user)))
#define EMBEDDEDEDITOR_WM_GET_USER_DATA (EMBEDDEDEDITOR_WM_FIRST + 7)
#define EMBEDDEDEDITOR_GET_USER_DATA(/*HWND*/ _hwnd)\
((void*)SendMessageW((_hwnd), EMBEDDEDEDITOR_WM_GET_USER_DATA, 0, 0L))
#define EMBEDDEDEDITOR_WM_SET_ANCHOR_POINT (EMBEDDEDEDITOR_WM_FIRST + 8)
#define EMBEDDEDEDITOR_SET_ANCHOR_POINT(/*HWND*/ _hwnd, /*long*/ _x, /*long*/ _y)\
((BOOL)SendMessageW((_hwnd), EMBEDDEDEDITOR_WM_SET_ANCHOR_POINT, (WPARAM)(_x), (LPARAM)(_y)))
#define EMBEDDEDEDITOR_WM_GET_ANCHOR_POINT (EMBEDDEDEDITOR_WM_FIRST + 9)
#define EMBEDDEDEDITOR_GET_ANCHOR_POINT(/*HWND*/ _hwnd, /*long* */ _x, /*long* */ _y)\
((BOOL)SendMessageW((_hwnd), EMBEDDEDEDITOR_WM_GET_ANCHOR_POINT, (WPARAM)(_x), (LPARAM)(_y)))
#define EMBEDDEDEDITOR_WM_SET_MAX_SIZE (EMBEDDEDEDITOR_WM_FIRST + 10)
#define EMBEDDEDEDITOR_SET_MAX_SIZE(/*HWND*/ _hwnd, /*long*/ _width, /*long*/ _height)\
((BOOL)SendMessageW((_hwnd), EMBEDDEDEDITOR_WM_SET_MAX_SIZE, (WPARAM)(_width), (LPARAM)(_height)))
#define EMBEDDEDEDITOR_WM_GET_MAX_SIZE (EMBEDDEDEDITOR_WM_FIRST + 11)
#define EMBEDDEDEDITOR_GET_MAX_SIZE(/*HWND*/ _hwnd, /*long* */ _width, /*long* */ _height)\
((BOOL)SendMessageW((_hwnd), EMBEDDEDEDITOR_GET_MAX_SIZE, (WPARAM)(_width), (LPARAM)(_height)))
#define EMBEDDEDEDITOR_WM_END_EDITING (EMBEDDEDEDITOR_WM_FIRST + 12)
#define EMBEDDEDEDITOR_END_EDITING(/*HWND*/ _hwnd, /*BOOL*/ _cancel)\
((BOOL)SendMessageW((_hwnd), EMBEDDEDEDITOR_WM_END_EDITING, (WPARAM)(_cancel), 0L))
#endif //_NULLSOFT_WINAMP_ML_DEVICES_EMBEDED_EDITOR_HEADER
@@ -0,0 +1,465 @@
#include "main.h"
#include "./eventRelay.h"
#include <vector>
#define EVENT_RELAY_WINDOW_CLASS L"NullsoftEventRelay"
typedef struct EventHandler
{
size_t cookie;
DeviceEventCallbacks callbacks;
void *user;
} EventHandler;
typedef std::vector<EventHandler*> EventHandlerList;
typedef struct EventRelay
{
EventHandlerList handlerList;
DeviceManagerHandler *managerHandler;
DeviceHandler *deviceHandler;
} EventRelay;
#define EVENTRELAY(_hwnd) ((EventRelay*)(LONGX86)GetWindowLongPtrW((_hwnd), 0))
#define EVENTRELAY_RET_VOID(_self, _hwnd) {(_self) = EVENTRELAY((_hwnd)); if (NULL == (_self)) return;}
#define EVENTRELAY_RET_VAL(_self, _hwnd, _error) {(_self) = EVENTRELAY((_hwnd)); if (NULL == (_self)) return (_error);}
static LRESULT CALLBACK
EventRelay_WindowProc(HWND hwnd, unsigned int uMsg, WPARAM wParam, LPARAM lParam);
static ATOM
EventRelay_GetClassAtom(HINSTANCE instance)
{
WNDCLASSEXW klass;
ATOM klassAtom;
klassAtom = (ATOM)GetClassInfoExW(instance, EVENT_RELAY_WINDOW_CLASS, &klass);
if (0 != klassAtom)
return klassAtom;
memset(&klass, 0, sizeof(klass));
klass.cbSize = sizeof(klass);
klass.style = 0;
klass.lpfnWndProc = EventRelay_WindowProc;
klass.cbClsExtra = 0;
klass.cbWndExtra = sizeof(EventRelay*);
klass.hInstance = instance;
klass.hIcon = NULL;
klass.hCursor = NULL;
klass.hbrBackground = NULL;
klass.lpszMenuName = NULL;
klass.lpszClassName = EVENT_RELAY_WINDOW_CLASS;
klass.hIconSm = NULL;
klassAtom = RegisterClassExW(&klass);
return klassAtom;
}
HWND
EventRelay_CreateWindow()
{
HINSTANCE instance;
ATOM klassAtom;
HWND hwnd;
instance = GetModuleHandleW(NULL);
klassAtom = EventRelay_GetClassAtom(instance);
if (0 == klassAtom)
return NULL;
hwnd = CreateWindowEx(WS_EX_NOACTIVATE | WS_EX_NOPARENTNOTIFY,
MAKEINTATOM(klassAtom),
NULL,
WS_OVERLAPPED,
0, 0, 0, 0,
HWND_MESSAGE,
NULL,
instance,
NULL);
return hwnd;
}
static size_t
EventRelay_GenerateCookie(EventRelay *self)
{
size_t cookie;
EventHandler *handler;
if (NULL == self)
return 0;
cookie = self->handlerList.size() + 1;
for(;;)
{
size_t index = self->handlerList.size();
while(index--)
{
handler = self->handlerList[index];
if (cookie == handler->cookie)
{
cookie++;
break;
}
}
if (((size_t)-1) == index)
return cookie;
}
return cookie;
}
static EventHandler *
EventRelay_CreateEventHandler(EventRelay *self, DeviceEventCallbacks *callbacks, void *user)
{
EventHandler *handler;
size_t cookie;
if (NULL == self || NULL == callbacks)
return NULL;
cookie = EventRelay_GenerateCookie(self);
if (0 == cookie)
return NULL;
handler = (EventHandler*)malloc(sizeof(EventHandler));
if (NULL == handler)
return NULL;
handler->user = user;
handler->cookie = cookie;
handler->callbacks.deviceCb = callbacks->deviceCb;
handler->callbacks.typeCb = callbacks->typeCb;
handler->callbacks.connectionCb = callbacks->connectionCb;
handler->callbacks.commandCb = callbacks->commandCb;
handler->callbacks.discoveryCb = callbacks->discoveryCb;
return handler;
}
static void
EventRelay_DestroyEventHandler(EventHandler *handler)
{
if (NULL == handler)
return;
free(handler);
}
static LRESULT
EventRelay_OnCreate(HWND hwnd, CREATESTRUCT *createStruct)
{
EventRelay *self;
ifc_deviceobjectenum *enumerator;
ifc_deviceobject *object;
ifc_device *device;
if (NULL == WASABI_API_DEVICES)
return -1;
self = new EventRelay();
if (NULL == self)
return -1;
self->deviceHandler = NULL;
self->managerHandler = NULL;
SetLastError(ERROR_SUCCESS);
if (!SetWindowLongPtr(hwnd, 0, (LONGX86)self) && ERROR_SUCCESS != GetLastError())
return -1;
if (FAILED(DeviceHandler::CreateInstance(&self->deviceHandler)))
return -1;
self->deviceHandler->SetRelayWindow(hwnd);
if (SUCCEEDED(WASABI_API_DEVICES->DeviceEnumerate(&enumerator)))
{
while(S_OK == enumerator->Next(&object, 1, NULL))
{
if (SUCCEEDED(object->QueryInterface(IFC_Device, (void**)&device)))
{
self->deviceHandler->Advise(device);
device->Release();
}
object->Release();
}
enumerator->Release();
}
if (FAILED(DeviceManagerHandler::CreateInstance(&self->managerHandler)))
return -1;
self->managerHandler->SetRelayWindow(hwnd);
if (FAILED(self->managerHandler->Advise(WASABI_API_DEVICES)))
return -1;
return 0;
}
static void
EventRelay_OnDestroy(HWND hwnd)
{
EventRelay *self;
MSG msg;
self = EVENTRELAY(hwnd);
SetWindowLongPtr(hwnd, 0, 0);
if (NULL == self)
return;
size_t index = self->handlerList.size();
while(index--)
{
EventHandler *handler = self->handlerList[index];
EventRelay_DestroyEventHandler(handler);
}
if (NULL != self->managerHandler)
{
self->managerHandler->SetRelayWindow(NULL);
if (NULL != WASABI_API_DEVICES)
self->managerHandler->Unadvise(WASABI_API_DEVICES);
self->managerHandler->Release();
}
if (NULL != self->deviceHandler)
{
self->deviceHandler->SetRelayWindow(NULL);
if (NULL != WASABI_API_DEVICES)
{
ifc_deviceobjectenum *enumerator;
ifc_deviceobject *object;
ifc_device *device;
if (SUCCEEDED(WASABI_API_DEVICES->DeviceEnumerate(&enumerator)))
{
while(S_OK == enumerator->Next(&object, 1, NULL))
{
if (SUCCEEDED(object->QueryInterface(IFC_Device, (void**)&device)))
{
self->deviceHandler->Unadvise(device);
device->Release();
}
object->Release();
}
enumerator->Release();
}
}
self->deviceHandler->Release();
}
delete self;
// finish pumping messages
while(FALSE != PeekMessage(&msg, hwnd, EVENTRELAY_WM_FIRST, EVENTRELAY_WM_LAST, PM_REMOVE))
{
EventRelay_WindowProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
}
}
static LRESULT
EventRelay_OnRegisterHandler(HWND hwnd, DeviceEventCallbacks *callbacks, void *user)
{
EventRelay *self;
EventHandler *handler;
EVENTRELAY_RET_VAL(self, hwnd, 0);
handler = EventRelay_CreateEventHandler(self, callbacks, user);
if(NULL == handler)
return 0;
self->handlerList.push_back(handler);
return (LRESULT)handler->cookie;
}
static LRESULT
EventRelay_OnUnregisterHandler(HWND hwnd, size_t cookie)
{
EventRelay *self;
EVENTRELAY_RET_VAL(self, hwnd, FALSE);
size_t index = self->handlerList.size();
while(index--)
{
EventHandler *handler = self->handlerList[index];
if (handler->cookie == cookie)
{
self->handlerList.erase(self->handlerList.begin() + index);
EventRelay_DestroyEventHandler(handler);
return TRUE;
}
}
return FALSE;
}
static void
EventRelay_OnNotifyDevice(HWND hwnd, ifc_device *device, DeviceEvent eventId)
{
ReplyMessage(0);
if (NULL != device)
{
EventRelay *self;
self = EVENTRELAY(hwnd);
if (NULL != self)
{
switch(eventId)
{
case Event_DeviceAdded:
if (NULL != self->deviceHandler)
self->deviceHandler->Advise(device);
break;
case Event_DeviceRemoved:
if (NULL != self->deviceHandler)
self->deviceHandler->Unadvise(device);
break;
}
size_t index = self->handlerList.size();
while(index--)
{
EventHandler *handler = self->handlerList[index];
if (NULL != handler->callbacks.deviceCb)
handler->callbacks.deviceCb(device, eventId, handler->user);
}
}
device->Release();
}
}
static void
EventRelay_OnNotifyDiscovery(HWND hwnd, api_devicemanager *manager, DeviceDiscoveryEvent eventId)
{
ReplyMessage(0);
if (NULL != manager)
{
EventRelay *self;
self = EVENTRELAY(hwnd);
if (NULL != self)
{
size_t index = self->handlerList.size();
while(index--)
{
EventHandler *handler = self->handlerList[index];
if (NULL != handler->callbacks.discoveryCb)
handler->callbacks.discoveryCb(manager, eventId, handler->user);
}
}
manager->Release();
}
}
static void
EventRelay_OnNotifyType(HWND hwnd, ifc_devicetype *type, DeviceTypeEvent eventId)
{
ReplyMessage(0);
if (NULL != type)
{
EventRelay *self;
self = EVENTRELAY(hwnd);
if (NULL != self)
{
size_t index = self->handlerList.size();
while(index--)
{
EventHandler *handler = self->handlerList[index];
if (NULL != handler->callbacks.typeCb)
handler->callbacks.typeCb(type, eventId, handler->user);
}
}
type->Release();
}
}
static void
EventRelay_OnNotifyConnection(HWND hwnd, ifc_deviceconnection *connection, DeviceConnectionEvent eventId)
{
ReplyMessage(0);
if (NULL != connection)
{
EventRelay *self;
self = EVENTRELAY(hwnd);
if (NULL != self)
{
size_t index = self->handlerList.size();
while(index--)
{
EventHandler *handler = self->handlerList[index];
if (NULL != handler->callbacks.connectionCb)
handler->callbacks.connectionCb(connection, eventId, handler->user);
}
}
connection->Release();
}
}
static void
EventRelay_OnNotifyCommand(HWND hwnd, ifc_devicecommand *command, DeviceCommandEvent eventId)
{
ReplyMessage(0);
if (NULL != command)
{
EventRelay *self;
self = EVENTRELAY(hwnd);
if (NULL != self)
{
size_t index = self->handlerList.size();
while(index--)
{
EventHandler *handler = self->handlerList[index];
if (NULL != handler->callbacks.commandCb)
handler->callbacks.commandCb(command, eventId, handler->user);
}
}
command->Release();
}
}
static LRESULT CALLBACK
EventRelay_WindowProc(HWND hwnd, unsigned int uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_CREATE: return EventRelay_OnCreate(hwnd, (CREATESTRUCT*)lParam);
case WM_DESTROY: EventRelay_OnDestroy(hwnd); return 0;
case EVENTRELAY_WM_REGISTER_HANDLER: return EventRelay_OnRegisterHandler(hwnd, (DeviceEventCallbacks*)lParam, (void*)wParam);
case EVENTRELAY_WM_UNREGISTER_HANDLER: return EventRelay_OnUnregisterHandler(hwnd, (size_t)lParam);
case EVENTRELAY_WM_NOTIFY_DEVICE: EventRelay_OnNotifyDevice(hwnd, (ifc_device*)lParam, (DeviceEvent)wParam); return 0;
case EVENTRELAY_WM_NOTIFY_DISCOVERY: EventRelay_OnNotifyDiscovery(hwnd, (api_devicemanager*)lParam, (DeviceDiscoveryEvent)wParam); return 0;
case EVENTRELAY_WM_NOTIFY_TYPE: EventRelay_OnNotifyType(hwnd, (ifc_devicetype*)lParam, (DeviceTypeEvent)wParam); return 0;
case EVENTRELAY_WM_NOTIFY_CONNECTION: EventRelay_OnNotifyConnection(hwnd, (ifc_deviceconnection*)lParam, (DeviceConnectionEvent)wParam); return 0;
case EVENTRELAY_WM_NOTIFY_COMMAND: EventRelay_OnNotifyCommand(hwnd, (ifc_devicecommand*)lParam, (DeviceCommandEvent)wParam); return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
+116
View File
@@ -0,0 +1,116 @@
#ifndef _NULLSOFT_WINAMP_ML_DEVICES_EVENT_RELAY_HEADER
#define _NULLSOFT_WINAMP_ML_DEVICES_EVENT_RELAY_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
typedef enum DeviceEvent
{
Event_DeviceAdded = 1,
Event_DeviceRemoved = 2,
Event_DeviceIconChanged = 3,
Event_DeviceDisplayNameChanged = 4,
Event_DeviceAttached = 5,
Event_DeviceDetached = 6,
Event_DeviceHidden = 7,
Event_DeviceShown = 8,
Event_DeviceTotalSpaceChanged = 9,
Event_DeviceUsedSpaceChanged = 10,
Event_DeviceCommandChanged = 11,
Event_DeviceActivityStarted = 12,
Event_DeviceActivityFinished = 13,
Event_DeviceActivityChanged = 14,
Event_DeviceModelChanged = 15,
Event_DeviceStatusChanged = 16,
} DeviceEvent;
typedef enum DeviceTypeEvent
{
Event_TypeRegistered = 1,
Event_TypeUnregistered = 2,
} DeviceTypeEvent;
typedef enum DeviceConnectionEvent
{
Event_ConnectionRegistered = 1,
Event_ConnectionUnregistered = 2,
} DeviceConnectionEvent;
typedef enum DeviceCommandEvent
{
Event_CommandRegistered = 1,
Event_CommandUnregistered = 2,
} DeviceCommandEvent;
typedef enum DeviceDiscoveryEvent
{
Event_DiscoveryStarted = 1,
Event_DiscoveryFinished = 2,
} DeviceDiscoveryEvent;
typedef void (*DeviceEventCb)(ifc_device *device, DeviceEvent eventId, void *user);
typedef void (*DeviceTypeEventCb)(ifc_devicetype *type, DeviceTypeEvent eventId, void *user);
typedef void (*DeviceConnectionEventCb)(ifc_deviceconnection *connection, DeviceConnectionEvent eventId, void *user);
typedef void (*DeviceCommandEventCb)(ifc_devicecommand *command, DeviceCommandEvent eventId, void *user);
typedef void (*DeviceDiscoveryEventCb)(api_devicemanager *manager, DeviceDiscoveryEvent eventId, void *user);
typedef struct DeviceEventCallbacks
{
DeviceEventCb deviceCb;
DeviceTypeEventCb typeCb;
DeviceConnectionEventCb connectionCb;
DeviceCommandEventCb commandCb;
DeviceDiscoveryEventCb discoveryCb;
} DeviceEventCallbacks;
HWND
EventRelay_CreateWindow();
#define EVENTRELAY_WM_FIRST (WM_USER + 10)
#define EVENTRELAY_WM_REGISTER_HANDLER (EVENTRELAY_WM_FIRST + 0)
#define EVENTRELAY_REGISTER_HANDLER(/*HWND*/ _hwnd, /*DeviceEventCallbacks*/ _handler, /*void* */ _user)\
((size_t)SendMessageW((_hwnd), EVENTRELAY_WM_REGISTER_HANDLER, (WPARAM)(_user), (LPARAM)(_handler)))
#define EVENTRELAY_WM_UNREGISTER_HANDLER (EVENTRELAY_WM_FIRST + 1)
#define EVENTRELAY_UNREGISTER_HANDLER(/*HWND*/ _hwnd, /*size_t*/ _handlerCookie)\
((BOOL)SendMessageW((_hwnd), EVENTRELAY_WM_UNREGISTER_HANDLER, 0, (LPARAM)(_handlerCookie)))
#define EVENTRELAY_WM_NOTIFY_DEVICE (EVENTRELAY_WM_FIRST + 2)
#define EVENTRELAY_NOTIFY_DEVICE(/*HWND*/ _hwnd, /*ifc_device* */ _device, /*DeviceEvent*/ _eventId)\
{ ifc_device *_d = (_device); if (NULL != _d && NULL != (_hwnd)) { _d->AddRef(); \
if (FALSE == ((BOOL)PostMessageW((_hwnd), EVENTRELAY_WM_NOTIFY_DEVICE,\
(WPARAM)(_eventId), (LPARAM)(_d)))) { _d->Release(); }}}
#define EVENTRELAY_WM_NOTIFY_DISCOVERY (EVENTRELAY_WM_FIRST + 3)
#define EVENTRELAY_NOTIFY_DISCOVERY(/*HWND*/ _hwnd, /*api_devicemanager* */ _manager, /*DeviceDiscoveryEvent*/ _eventId)\
{ api_devicemanager *_m = (_manager); if (NULL != _m && NULL != (_hwnd)) { _m->AddRef(); \
if (FALSE == ((BOOL)PostMessageW((_hwnd), EVENTRELAY_WM_NOTIFY_DISCOVERY,\
(WPARAM)(_eventId), (LPARAM)(_m)))) { _m->Release(); }}}
#define EVENTRELAY_WM_NOTIFY_TYPE (EVENTRELAY_WM_FIRST + 4)
#define EVENTRELAY_NOTIFY_TYPE(/*HWND*/ _hwnd, /*ifc_devicetype* */ _type, /*DeviceTypeEvent*/ _eventId)\
{ ifc_devicetype *_t = (_type); if (NULL != _t && NULL != (_hwnd)) { _t->AddRef(); \
if (FALSE == ((BOOL)PostMessageW((_hwnd), EVENTRELAY_WM_NOTIFY_TYPE,\
(WPARAM)(_eventId), (LPARAM)(_t)))) { _t->Release(); }}}
#define EVENTRELAY_WM_NOTIFY_CONNECTION (EVENTRELAY_WM_FIRST + 5)
#define EVENTRELAY_NOTIFY_CONNECTION(/*HWND*/ _hwnd, /*ifc_deviceconnection* */ _connection, /*DeviceConnectionEvent*/ _eventId)\
{ ifc_deviceconnection *_c = (_connection); if (NULL != _c && NULL != (_hwnd)) { _c->AddRef(); \
if (FALSE == ((BOOL)PostMessageW((_hwnd), EVENTRELAY_WM_NOTIFY_CONNECTION,\
(WPARAM)(_eventId), (LPARAM)(_c)))) { _c->Release(); }}}
#define EVENTRELAY_WM_NOTIFY_COMMAND (EVENTRELAY_WM_FIRST + 6)
#define EVENTRELAY_NOTIFY_COMMAND(/*HWND*/ _hwnd, /*ifc_devicecommand* */ _command, /*DeviceCommandEvent*/ _eventId)\
{ ifc_devicecommand *_c = (_command); if (NULL != _c && NULL != (_hwnd)) { _c->AddRef(); \
if (FALSE == ((BOOL)PostMessageW((_hwnd), EVENTRELAY_WM_NOTIFY_COMMAND,\
(WPARAM)(_eventId), (LPARAM)(_c)))) { _c->Release(); }}}
#define EVENTRELAY_WM_LAST EVENTRELAY_WM_NOTIFY_COMMAND
#endif //_NULLSOFT_WINAMP_ML_DEVICES_EVENT_RELAY_HEADER
@@ -0,0 +1,134 @@
#include "main.h"
#include "./fillRegion.h"
static BOOL
FillRegion_TempRegionFromRect(FillRegion *region, const RECT *rect)
{
if (NULL == region || NULL == rect)
return FALSE;
if (NULL == region->tmp)
{
region->tmp = CreateRectRgn(rect->left, rect->top, rect->right, rect->bottom);
if (NULL == region->tmp)
return FALSE;
}
else
{
if (FALSE == SetRectRgn(region->tmp, rect->left, rect->top, rect->right, rect->bottom))
return FALSE;
}
return TRUE;
}
BOOL
FillRegion_Init(FillRegion *region, const RECT *rect)
{
if (NULL == region)
return FALSE;
region->fill = (NULL != rect) ?
CreateRectRgn(rect->left, rect->top, rect->right, rect->bottom) :
NULL;
region->tmp = NULL;
if (NULL == region->fill)
return FALSE;
return TRUE;
}
void
FillRegion_Uninit(FillRegion *region)
{
if (NULL != region)
{
if (NULL != region->fill)
{
DeleteObject(region->fill);
region->fill = NULL;
}
if (NULL != region->tmp)
{
DeleteObject(region->tmp);
region->tmp = NULL;
}
}
}
BOOL
FillRegion_ExcludeRect(FillRegion *region, const RECT *rect)
{
if (NULL == region || NULL == rect)
return FALSE;
return (FALSE != FillRegion_TempRegionFromRect(region, rect) &&
ERROR != CombineRgn(region->fill, region->fill, region->tmp, RGN_DIFF));
}
BOOL
FillRegion_ExcludeRgn(FillRegion *region, HRGN rgn)
{
if (NULL == region || NULL == rgn)
return FALSE;
return (ERROR != CombineRgn(region->fill, region->fill, rgn, RGN_DIFF));
}
BOOL
FillRegion_AppendRect(FillRegion *region, const RECT *rect)
{
if (NULL == region || NULL == rect)
return FALSE;
return (FALSE != FillRegion_TempRegionFromRect(region, rect) &&
ERROR != CombineRgn(region->fill, region->fill, region->tmp, RGN_OR));
}
BOOL
FillRegion_AppendRgn(FillRegion *region, HRGN rgn)
{
if (NULL == region || NULL == rgn)
return FALSE;
return (ERROR != CombineRgn(region->fill, region->fill, rgn, RGN_OR));
}
BOOL
FillRegion_BrushFill(FillRegion *region, HDC hdc, HBRUSH brush)
{
if (NULL == region)
return FALSE;
return FillRgn(hdc, region->fill, brush);
}
BOOL
FillRegion_Offset(FillRegion *region, long x, long y)
{
if (NULL == region)
return FALSE;
return (ERROR != OffsetRgn(region->fill, x, y));
}
BOOL
FillRegion_SetRect(FillRegion *region, const RECT *rect)
{
if (NULL == region || NULL == rect)
return FALSE;
return SetRectRgn(region->fill, rect->left, rect->top, rect->right, rect->bottom);
}
BOOL
FillRegion_SetEmpty(FillRegion *region)
{
if (NULL == region)
return FALSE;
return SetRectRgn(region->fill, 0, 0, 0, 0);
}
@@ -0,0 +1,51 @@
#ifndef _NULLSOFT_WINAMP_ML_DEVICES_FILL_REGION_HEADER
#define _NULLSOFT_WINAMP_ML_DEVICES_FILL_REGION_HEADER
typedef struct FillRegion
{
HRGN fill;
HRGN tmp;
} FillRegion;
BOOL
FillRegion_Init(FillRegion *region,
const RECT *rect);
void
FillRegion_Uninit(FillRegion *region);
BOOL
FillRegion_ExcludeRect(FillRegion *region,
const RECT *rect);
BOOL
FillRegion_ExcludeRgn(FillRegion *region,
HRGN rgn);
BOOL
FillRegion_AppendRect(FillRegion *region,
const RECT *rect);
BOOL
FillRegion_AppendRgn(FillRegion *region,
HRGN rgn);
BOOL
FillRegion_BrushFill(FillRegion *region,
HDC hdc,
HBRUSH brush);
BOOL
FillRegion_Offset(FillRegion *region,
long x,
long y);
BOOL
FillRegion_SetRect(FillRegion *region,
const RECT *rect);
BOOL
FillRegion_SetEmpty(FillRegion *region);
#endif //_NULLSOFT_WINAMP_ML_DEVICES_FILL_REGION_HEADER
@@ -0,0 +1,76 @@
#ifndef _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_COMMON_HEADER
#define _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_COMMON_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#ifndef LONGX86
#ifdef _WIN64
#define LONGX86 LONG_PTR
#else /*_WIN64*/
#define LONGX86 LONG
#endif /*_WIN64*/
#endif // LONGX86
#define CSTR_INVARIANT MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT)
#ifdef __cplusplus
#define SENDMSG(__hwnd, __msgId, __wParam, __lParam) ::SendMessageW((__hwnd), (__msgId), (__wParam), (__lParam))
#else
#define SENDMSG(__hwnd, __msgId, __wParam, __lParam) SendMessageW((__hwnd), (__msgId), (__wParam), (__lParam))
#endif // __cplusplus
#define SENDMLIPC(__hwndML, __ipcMsgId, __param) SENDMSG((__hwndML), WM_ML_IPC, (WPARAM)(__param), (LPARAM)(__ipcMsgId))
#define SENDWAIPC(__hwndWA, __ipcMsgId, __param) SENDMSG((__hwndWA), WM_WA_IPC, (WPARAM)(__param), (LPARAM)(__ipcMsgId))
#define SENDCMD(__hwnd, __ctrlId, __eventId, __hctrl) (SENDMSG((__hwnd), WM_COMMAND, MAKEWPARAM(__ctrlId, __eventId), (LPARAM)(__hctrl)))
#define DIALOG_RESULT(__hwnd, __result) { SetWindowLongPtrW((__hwnd), DWLP_MSGRESULT, ((LONGX86)(LONG_PTR)(__result))); return TRUE; }
#ifndef GetWindowStyle
#define GetWindowStyle(__hwnd) ((UINT)GetWindowLongPtr((__hwnd), GWL_STYLE))
#endif //GetWindowStyle
#ifndef SetWindowStyle
#define SetWindowStyle(__hwnd, __style) (SetWindowLongPtr((__hwnd), GWL_STYLE, (__style)))
#endif //SetWindowStyle
#ifndef GetWindowStyleEx
#define GetWindowStyleEx(__hwnd) ((UINT)GetWindowLongPtr((__hwnd), GWL_EXSTYLE))
#endif // GetWindowStyleEx
#ifndef SetWindowStyleEx
#define SetWindowStyleEx(__hwnd, __style) (SetWindowLongPtr((__hwnd), GWL_EXSTYLE, (__style)))
#endif //SetWindowStyle
#ifndef RECTWIDTH
#define RECTWIDTH(__r) ((__r).right - (__r).left)
#endif
#ifndef RECTHEIGHT
#define RECTHEIGHT(__r) ((__r).bottom - (__r).top)
#endif
#undef CLAMP
#define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)))
#ifndef ARRAYSIZE
#define ARRAYSIZE(_a) (sizeof(_a)/sizeof((_a)[0]))
#endif
#ifndef ABS
#define ABS(x) (((x) > 0) ? (x) : (-x))
#endif
#ifndef MIN
#define MIN(v1, v2) (((v1) < (v2)) ? (v1) : (v2))
#endif
#ifndef MAX
#define MAX(v1, v2) (((v1) > (v2)) ? (v1) : (v2))
#endif
#endif //_NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_COMMON_HEADER
@@ -0,0 +1,871 @@
#include "main.h"
#include "./device.h"
#include <strsafe.h>
Device::Device()
: ref(1), name(NULL), type(NULL), connection(NULL), displayName(NULL),
totalSpace(0), usedSpace(0), attached(FALSE), hidden(FALSE),
connected(FALSE), activity(NULL), model(NULL), status(NULL)
{
InitializeCriticalSection(&lock);
if (NULL == WASABI_API_DEVICES ||
FAILED(WASABI_API_DEVICES->CreateDeviceEventManager(&eventManager)))
{
eventManager = NULL;
}
if (NULL == WASABI_API_DEVICES ||
FAILED(WASABI_API_DEVICES->CreateIconStore(&iconStore)))
{
iconStore = NULL;
}
if (NULL == WASABI_API_DEVICES ||
FAILED(WASABI_API_DEVICES->CreateSupportedCommandStore(&commands)))
{
commands = NULL;
}
}
Device::~Device()
{
DeviceActivity *activityCopy;
Lock();
if (NULL != activity)
{
activity->SetUser(NULL);
activityCopy = activity;
activityCopy->AddRef();
}
else
activityCopy = NULL;
AnsiString_Free(name);
AnsiString_Free(type);
AnsiString_Free(connection);
String_Free(displayName);
String_Free(model);
String_Free(status);
if (NULL != commands)
commands->Release();
if (NULL != iconStore)
iconStore->Release();
if (NULL != eventManager)
eventManager->Release();
Unlock();
if (NULL != activityCopy)
{
activityCopy->Stop();
activityCopy->Release();
}
DeleteCriticalSection(&lock);
}
HRESULT Device::CreateInstance(const char *name, const char *type, const char *connection, Device**instance)
{
Device *self;
if (NULL == instance)
return E_POINTER;
*instance = NULL;
self = new Device();
if (NULL == self)
return E_OUTOFMEMORY;
self->name = AnsiString_Duplicate(name);
self->type = AnsiString_Duplicate(type);
self->connection = AnsiString_Duplicate(connection);
*instance = self;
return S_OK;
}
size_t Device::AddRef()
{
return InterlockedIncrement((LONG*)&ref);
}
size_t Device::Release()
{
if (0 == ref)
return ref;
LONG r = InterlockedDecrement((LONG*)&ref);
if (0 == r)
delete(this);
return r;
}
int Device::QueryInterface(GUID interface_guid, void **object)
{
if (NULL == object)
return E_POINTER;
if (IsEqualIID(interface_guid, IFC_Device))
*object = static_cast<ifc_device*>(this);
else
{
*object = NULL;
return E_NOINTERFACE;
}
if (NULL == *object)
return E_UNEXPECTED;
AddRef();
return S_OK;
}
void Device::Lock()
{
EnterCriticalSection(&lock);
}
void Device::Unlock()
{
LeaveCriticalSection(&lock);
}
const char *Device::GetName()
{
return name;
}
const char *Device::GetType()
{
return type;
}
const char *Device::GetConnection()
{
return connection;
}
HRESULT Device::GetIcon(wchar_t *buffer, size_t bufferSize, int width, int height)
{
if (NULL == buffer)
return E_POINTER;
if (NULL == iconStore)
return E_UNEXPECTED;
return iconStore->Get(buffer, bufferSize, width, height);
}
HRESULT Device::GetDisplayName(wchar_t *buffer, size_t bufferSize)
{
HRESULT hr;
if (NULL == buffer)
return E_POINTER;
Lock();
if (0 == String_CopyTo(buffer, displayName, bufferSize) &&
FALSE == IS_STRING_EMPTY(displayName))
{
hr = E_FAIL;
}
else
hr = S_OK;
Unlock();
return hr;
}
BOOL Device::GetHidden()
{
return hidden;
}
HRESULT Device::GetTotalSpace(uint64_t *size)
{
if (NULL == size)
return E_POINTER;
Lock();
*size = totalSpace;
Unlock();
return S_OK;
}
HRESULT Device::GetUsedSpace(uint64_t *size)
{
if (NULL == size)
return E_POINTER;
Lock();
*size = usedSpace;
Unlock();
return S_OK;
}
BOOL Device::GetAttached()
{
return attached;
}
HRESULT Device::Attach(HWND hostWindow)
{
HRESULT hr;
Lock();
if (FALSE != attached)
hr = S_FALSE;
else
{
attached = TRUE;
hr = S_OK;
}
Unlock();
if (S_OK == hr && NULL != eventManager)
eventManager->Notify_AttachmentChanged(this, attached);
return hr;
}
HRESULT Device::Detach(HWND hostWindow)
{
HRESULT hr;
Lock();
if (FALSE == attached)
hr = S_FALSE;
else
{
attached = FALSE;
hr = S_OK;
}
Unlock();
if (S_OK == hr && NULL != eventManager)
eventManager->Notify_AttachmentChanged(this, attached);
return hr;
}
HRESULT Device::EnumerateCommands(ifc_devicesupportedcommandenum **enumerator, DeviceCommandContext context)
{
if (NULL == commands)
return E_UNEXPECTED;
return commands->Enumerate(enumerator);
}
HRESULT Device::SendCommand(const char *command, HWND hostWindow, ULONG_PTR param)
{
const wchar_t *commandName;
wchar_t message[1024];
if (NULL == command)
return E_POINTER;
if (CSTR_EQUAL == CompareStringA(CSTR_INVARIANT, NORM_IGNORECASE, command, -1, "sync", -1))
{
StartSyncActivity(hostWindow);
return S_OK;
}
else if (CSTR_EQUAL == CompareStringA(CSTR_INVARIANT, NORM_IGNORECASE, command, -1, "eject", -1))
commandName = L"Eject";
else if (CSTR_EQUAL == CompareStringA(CSTR_INVARIANT, NORM_IGNORECASE, command, -1, "detach", -1))
{
Detach(hostWindow);
return S_OK;
}
else if (CSTR_EQUAL == CompareStringA(CSTR_INVARIANT, NORM_IGNORECASE, command, -1, "settings", -1))
commandName = L"Settings";
else
return E_NOTIMPL;
StringCchPrintf(message, ARRAYSIZE(message), L"%s command received", commandName);
MessageBox(hostWindow, message, L"Device command test", MB_OK | MB_ICONINFORMATION);
return S_OK;
}
HRESULT Device::GetCommandFlags(const char *command, DeviceCommandFlags *flags)
{
if (NULL == commands)
return E_UNEXPECTED;
return commands->GetFlags(command, flags);
}
HRESULT Device::GetActivity(ifc_deviceactivity **activityOut)
{
HRESULT hr;
if (NULL == activityOut)
return E_POINTER;
Lock();
*activityOut = activity;
if (NULL != activity)
{
activity->AddRef();
hr = S_OK;
}
else
hr = S_FALSE;
Unlock();
return hr;
}
HRESULT Device::Advise(ifc_deviceevent *handler)
{
if (NULL == eventManager)
return E_UNEXPECTED;
return eventManager->Advise(handler);
}
HRESULT Device::Unadvise(ifc_deviceevent *handler)
{
if (NULL == eventManager)
return E_UNEXPECTED;
return eventManager->Unadvise(handler);
}
HWND Device::CreateView(HWND parentWindow)
{
return DeviceView_CreateWindow(parentWindow, this);
}
void Device::SetNavigationItem(void *navigationItem)
{
}
HRESULT Device::GetModel(wchar_t *buffer, size_t bufferSize)
{
HRESULT hr;
if (NULL == buffer)
return E_POINTER;
Lock();
if (0 == String_CopyTo(buffer, model, bufferSize) &&
FALSE == IS_STRING_EMPTY(model))
{
hr = E_FAIL;
}
else
hr = S_OK;
Unlock();
return hr;
}
HRESULT Device::GetStatus(wchar_t *buffer, size_t bufferSize)
{
HRESULT hr;
if (NULL == buffer)
return E_POINTER;
Lock();
if (0 == String_CopyTo(buffer, status, bufferSize) &&
FALSE == IS_STRING_EMPTY(status))
{
hr = E_FAIL;
}
else
hr = S_OK;
Unlock();
return hr;
}
HRESULT Device::SetConnection(const char *con)
{
Lock();
AnsiString_Free(connection);
connection = AnsiString_Duplicate(con);
Unlock();
return S_OK;
}
HRESULT Device::SetDisplayName(const wchar_t *name)
{
HRESULT hr;
Lock();
if (NULL == name && NULL == displayName)
hr = S_FALSE;
else
{
if (NULL != displayName &&
CSTR_EQUAL == CompareString(LOCALE_USER_DEFAULT, 0, name, -1, displayName, -1))
{
hr = S_FALSE;
}
else
{
wchar_t *string;
string = String_Duplicate(name);
if (NULL == string && NULL != name)
hr = E_FAIL;
else
{
String_Free(displayName);
displayName = string;
if (NULL != eventManager)
eventManager->Notify_DisplayNameChanged(this, displayName);
hr = S_OK;
}
}
}
Unlock();
return hr;
}
HRESULT Device::SetTotalSpace(uint64_t size)
{
Lock();
totalSpace = size;
if (NULL != eventManager)
eventManager->Notify_TotalSpaceChanged(this, totalSpace);
Unlock();
return S_OK;
}
HRESULT Device::SetUsedSpace(uint64_t size)
{
Lock();
usedSpace = size;
if (NULL != eventManager)
eventManager->Notify_UsedSpaceChanged(this, usedSpace);
Unlock();
return S_OK;
}
HRESULT Device::SetModel(const wchar_t *deviceModel)
{
HRESULT hr;
Lock();
if (NULL == deviceModel && NULL == model)
hr = S_FALSE;
else
{
if (NULL != model &&
CSTR_EQUAL == CompareString(LOCALE_USER_DEFAULT, 0, deviceModel, -1, model, -1))
{
hr = S_FALSE;
}
else
{
wchar_t *string;
string = String_Duplicate(deviceModel);
if (NULL == string && NULL != deviceModel)
hr = E_FAIL;
else
{
String_Free(model);
model = string;
if (NULL != eventManager)
eventManager->Notify_ModelChanged(this, model);
hr = S_OK;
}
}
}
Unlock();
return hr;
}
HRESULT Device::SetStatus(const wchar_t *deviceStatus)
{
HRESULT hr;
Lock();
if (NULL == deviceStatus && NULL == status)
hr = S_FALSE;
else
{
if (NULL != status &&
CSTR_EQUAL == CompareString(LOCALE_USER_DEFAULT, 0, deviceStatus, -1, status, -1))
{
hr = S_FALSE;
}
else
{
wchar_t *string;
string = String_Duplicate(deviceStatus);
if (NULL == string && NULL != deviceStatus)
hr = E_FAIL;
else
{
String_Free(status);
status = string;
if (NULL != eventManager)
eventManager->Notify_StatusChanged(this, status);
hr = S_OK;
}
}
}
Unlock();
return hr;
}
HRESULT Device::AddIcon(const wchar_t *path, unsigned int width, unsigned int height)
{
HRESULT hr;
if (NULL == iconStore)
return E_UNEXPECTED;
hr = iconStore->Add(path, width, height, TRUE);
if (SUCCEEDED(hr))
{
if (NULL != eventManager)
eventManager->Notify_IconChanged(this);
}
return hr;
}
HRESULT Device::EnumerateIcons(ifc_deviceiconstore::EnumeratorCallback callback, void *user)
{
if (NULL == iconStore)
return E_UNEXPECTED;
return iconStore->Enumerate(callback, user);
}
HRESULT Device::RemoveIcon(unsigned int width, unsigned int height)
{
HRESULT hr;
if (NULL == iconStore)
return E_UNEXPECTED;
hr = iconStore->Remove(width, height);
if (SUCCEEDED(hr))
{
if (NULL != eventManager)
eventManager->Notify_IconChanged(this);
}
return hr;
}
HRESULT Device::SetHidden(BOOL hiddenState)
{
HRESULT hr;
Lock();
if (hidden == (FALSE != hiddenState))
hr = S_FALSE;
else
{
hidden = (FALSE != hiddenState);
hr = S_OK;
}
Unlock();
if (S_OK == hr && NULL != eventManager)
eventManager->Notify_VisibilityChanged(this, TRUE);
return hr;
}
HRESULT Device::IsConnected()
{
HRESULT hr;
Lock();
hr = (FALSE != connected) ? S_OK : S_FALSE;
Unlock();
return hr;
}
HRESULT Device::Connect()
{
HRESULT hr;
Lock();
if (FALSE != connected)
hr = S_FALSE;
else
{
connected = TRUE;
hr = S_OK;
}
Unlock();
return hr;
}
HRESULT Device::Disconnect()
{
HRESULT hr;
Lock();
if (FALSE == connected)
hr = S_FALSE;
else
{
connected = FALSE;
hr = S_OK;
}
Unlock();
return hr;
}
HRESULT Device::CopyTo(Device *target)
{
if (NULL == target)
return E_POINTER;
Lock();
target->SetDisplayName(displayName);
if (NULL != target->iconStore)
target->iconStore->Release();
if (NULL == iconStore || FAILED(iconStore->Clone(&target->iconStore)))
target->iconStore = NULL;
target->usedSpace = usedSpace;
target->totalSpace = totalSpace;
target->hidden = hidden;
target->attached = attached;
target->connected = connected;
if (NULL != target->commands)
target->commands->Release();
if (NULL == commands || FAILED(commands->Clone(&target->commands, TRUE)))
target->commands = NULL;
Unlock();
return S_OK;
}
HRESULT Device::SetIconBase(const wchar_t *path)
{
if (NULL == iconStore)
return E_UNEXPECTED;
return iconStore->SetBasePath(path);
}
HRESULT Device::AddCommand(const char *command, DeviceCommandFlags flags)
{
if (NULL == commands)
return E_UNEXPECTED;
return commands->Add(command, flags);
}
HRESULT Device::RemoveCommand(const char *command)
{
if (NULL == commands)
return E_UNEXPECTED;
return commands->Remove(command);
}
HRESULT Device::SetCommandFlags(const char *command, DeviceCommandFlags mask, DeviceCommandFlags flags)
{
if (NULL == commands)
return E_UNEXPECTED;
return commands->SetFlags(command, mask, flags);
}
void Device::ActivityStartedCb(DeviceActivity *activity)
{
Device *device;
if(FAILED(activity->GetUser((void**)&device)) || NULL == device)
return;
if (NULL != device->eventManager)
device->eventManager->Notify_ActivityStarted(device, activity);
}
void Device::ActivityFinishedCb(DeviceActivity *activity)
{
Device *device;
if(FAILED(activity->GetUser((void**)&device)) || NULL == device)
return;
device->Lock();
if (activity == device->activity)
device->activity = NULL;
device->Unlock();
if (NULL != device->eventManager)
device->eventManager->Notify_ActivityFinished(device, activity);
activity->Release();
}
void Device::ActivityProgressCb(DeviceActivity *activity, unsigned int progress, unsigned int duration)
{
Device *device;
uint64_t space;
if(FAILED(activity->GetUser((void**)&device)) || NULL == device)
return;
device->Lock();
space = device->usedSpace;
space++;
if (space > device->totalSpace)
space = 0;
device->Unlock();
device->SetUsedSpace(space);
if (NULL != device->eventManager)
device->eventManager->Notify_ActivityChanged(device, activity);
}
HRESULT Device::StartSyncActivity(HWND hostWindow)
{
HRESULT hr;
Lock();
if (NULL != activity)
hr = E_PENDING;
else
{
hr = DeviceActivity::CreateInstance(DeviceActivityFlag_Cancelable | DeviceActivityFlag_SupportProgress,
ActivityStartedCb, ActivityFinishedCb, ActivityProgressCb,
this, &activity);
if (SUCCEEDED(hr))
{
activity->SetDisplayName(L"Synchronizing...");
activity->SetStatus(L"Performing synchronization...");
hr = activity->Start(60000, 20);
if (FAILED(hr))
{
activity->Release();
activity = NULL;
}
}
}
Unlock();
return S_OK;
}
#define CBCLASS Device
START_DISPATCH;
CB(ADDREF, AddRef)
CB(RELEASE, Release)
CB(QUERYINTERFACE, QueryInterface)
CB(API_GETNAME, GetName)
CB(API_GETTYPE, GetType)
CB(API_GETCONNECTION, GetConnection)
CB(API_GETICON, GetIcon)
CB(API_GETDISPLAYNAME, GetDisplayName)
CB(API_GETHIDDEN, GetHidden)
CB(API_GETTOTALSPACE, GetTotalSpace)
CB(API_GETUSEDSPACE, GetUsedSpace)
CB(API_GETATTACHED, GetAttached)
CB(API_ATTACH, Attach)
CB(API_DETACH, Detach)
CB(API_ENUMERATECOMMANDS, EnumerateCommands)
CB(API_SENDCOMMAND, SendCommand)
CB(API_GETCOMMANDFLAGS, GetCommandFlags)
CB(API_GETACTIVITY, GetActivity)
CB(API_ADVISE, Advise)
CB(API_UNADVISE, Unadvise)
CB(API_CREATEVIEW, CreateView)
VCB(API_SETNAVIGATIONITEM, SetNavigationItem)
CB(API_SETDISPLAYNAME, SetDisplayName)
CB(API_GETMODEL, GetModel)
CB(API_GETSTATUS, GetStatus)
END_DISPATCH;
#undef CBCLASS
@@ -0,0 +1,114 @@
#ifndef _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_HEADER
#define _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
class DeviceActivity;
class Device: public ifc_device
{
protected:
Device();
~Device();
public:
static HRESULT CreateInstance(const char *name,
const char *type,
const char *connection,
Device**instance);
public:
/* Dispatchable */
size_t AddRef();
size_t Release();
int QueryInterface(GUID interface_guid, void **object);
/* ifc_device */
const char *GetName();
const char *GetType();
const char *GetConnection();
HRESULT GetIcon(wchar_t *buffer, size_t bufferSize, int width, int height);
HRESULT GetDisplayName(wchar_t *buffer, size_t bufferSize);
BOOL GetHidden();
HRESULT GetTotalSpace(uint64_t *size);
HRESULT GetUsedSpace(uint64_t *size);
BOOL GetAttached();
HRESULT Attach(HWND hostWindow);
HRESULT Detach(HWND hostWindow);
HRESULT EnumerateCommands(ifc_devicesupportedcommandenum **enumerator, DeviceCommandContext context);
HRESULT SendCommand(const char *command, HWND hostWindow, ULONG_PTR param);
HRESULT GetCommandFlags(const char *command, DeviceCommandFlags *flags);
HRESULT GetActivity(ifc_deviceactivity **activity);
HRESULT Advise(ifc_deviceevent *handler);
HRESULT Unadvise(ifc_deviceevent *handler);
HWND CreateView(HWND parentWindow);
void SetNavigationItem(void *navigationItem);
HRESULT GetModel(wchar_t *buffer, size_t bufferSize);
HRESULT GetStatus(wchar_t *buffer, size_t bufferSize);
public:
HRESULT SetConnection(const char *connection);
HRESULT SetDisplayName(const wchar_t *name);
HRESULT SetTotalSpace(uint64_t size);
HRESULT SetUsedSpace(uint64_t size);
HRESULT SetHidden(BOOL hiddenState);
HRESULT SetModel(const wchar_t *deviceModel);
HRESULT SetStatus(const wchar_t *deviceStatus);
HRESULT AddIcon(const wchar_t *path, unsigned int width, unsigned int height);
HRESULT EnumerateIcons(ifc_deviceiconstore::EnumeratorCallback callback, void *user);
HRESULT RemoveIcon(unsigned int width, unsigned int height);
HRESULT AddCommand(const char *command, DeviceCommandFlags flags);
HRESULT RemoveCommand(const char *command);
HRESULT SetCommandFlags(const char *command, DeviceCommandFlags mask, DeviceCommandFlags flags);
HRESULT IsConnected();
HRESULT Connect();
HRESULT Disconnect();
HRESULT CopyTo(Device *target);
HRESULT SetIconBase(const wchar_t *path);
HRESULT StartSyncActivity(HWND hostWindow);
protected:
void Lock();
void Unlock();
static void ActivityStartedCb(DeviceActivity *activity);
static void ActivityFinishedCb(DeviceActivity *activity);
static void ActivityProgressCb(DeviceActivity *activity, unsigned int progress, unsigned int duration);
protected:
size_t ref;
char *name;
char *type;
char *connection;
wchar_t *displayName;
wchar_t *model;
wchar_t *status;
uint64_t totalSpace;
uint64_t usedSpace;
BOOL attached;
BOOL hidden;
BOOL connected;
ifc_deviceiconstore *iconStore;
ifc_deviceeventmanager *eventManager;
ifc_devicesupportedcommandstore *commands;
DeviceActivity *activity;
CRITICAL_SECTION lock;
protected:
RECVS_DISPATCH;
};
#endif //_NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_HEADER
@@ -0,0 +1,519 @@
#include "main.h"
#include "./deviceActivity.h"
#include <strsafe.h>
typedef struct DeviceActivityThreadParam
{
DeviceActivity *activity;
unsigned int duration;
unsigned int interval;
HANDLE readyEvent;
}DeviceActivityThreadParam;
DeviceActivity::DeviceActivity(DeviceActivityFlags flags,
DeviceActivityCallback startCb, DeviceActivityCallback finishCb,
DeviceActivityProgressCallback progressCb, void *user)
: ref(1), displayName(NULL), status(NULL), activityThread(FALSE), cancelEvent(NULL), progress(0)
{
InitializeCriticalSection(&lock);
this->flags = flags;
callbackStart = startCb;
callbackFinish = finishCb;
callbackProgress = progressCb;
this->user = user;
}
DeviceActivity::~DeviceActivity()
{
Stop();
String_Free(displayName);
String_Free(status);
DeleteCriticalSection(&lock);
}
HRESULT DeviceActivity::CreateInstance(DeviceActivityFlags flags,
DeviceActivityCallback startCb, DeviceActivityCallback finishCb,
DeviceActivityProgressCallback progressCb, void *user,
DeviceActivity **instance)
{
DeviceActivity *self;
if (NULL == instance)
return E_POINTER;
*instance = NULL;
self = new DeviceActivity(flags, startCb, finishCb, progressCb, user);
if (NULL == self)
return E_OUTOFMEMORY;
*instance = self;
return S_OK;
}
size_t DeviceActivity::AddRef()
{
return InterlockedIncrement((LONG*)&ref);
}
size_t DeviceActivity::Release()
{
if (0 == ref)
return ref;
LONG r = InterlockedDecrement((LONG*)&ref);
if (0 == r)
delete(this);
return r;
}
int DeviceActivity::QueryInterface(GUID interface_guid, void **object)
{
if (NULL == object)
return E_POINTER;
if (IsEqualIID(interface_guid, IFC_DeviceActivity))
*object = static_cast<ifc_deviceactivity*>(this);
else
{
*object = NULL;
return E_NOINTERFACE;
}
if (NULL == *object)
return E_UNEXPECTED;
AddRef();
return S_OK;
}
void DeviceActivity::Lock()
{
EnterCriticalSection(&lock);
}
void DeviceActivity::Unlock()
{
LeaveCriticalSection(&lock);
}
BOOL DeviceActivity::GetActive()
{
BOOL running;
Lock();
running = (NULL != activityThread);
Unlock();
return running;
}
BOOL DeviceActivity::GetCancelable()
{
BOOL cancelable;
Lock();
cancelable = (0 != (DeviceActivityFlag_Cancelable & flags));
Unlock();
return cancelable;
}
HRESULT DeviceActivity::GetProgress(unsigned int *percentCompleted)
{
if (NULL == percentCompleted)
return E_POINTER;
Lock();
*percentCompleted = progress;
Unlock();
return S_OK;
}
HRESULT DeviceActivity::GetDisplayName(wchar_t *buffer, size_t bufferMax)
{
HRESULT hr;
if (NULL == buffer)
return E_POINTER;
Lock();
if (0 == String_CopyTo(buffer, displayName, bufferMax) &&
FALSE == IS_STRING_EMPTY(displayName))
{
hr = E_FAIL;
}
else
hr = S_OK;
Unlock();
return hr;
}
HRESULT DeviceActivity::GetStatus(wchar_t *buffer, size_t bufferMax)
{
HRESULT hr;
if (NULL == buffer)
return E_POINTER;
Lock();
if (0 == String_CopyTo(buffer, status, bufferMax) &&
FALSE == IS_STRING_EMPTY(status))
{
hr = E_FAIL;
}
else
hr = S_OK;
Unlock();
return hr;
}
HRESULT DeviceActivity::Cancel(HWND hostWindow)
{
HRESULT hr;
Lock();
if (0 == (DeviceActivityFlag_Cancelable & flags))
hr = E_NOTIMPL;
else
hr = E_FAIL;
Unlock();
return hr;
}
HRESULT DeviceActivity::Start(unsigned int duration, unsigned int interval)
{
HRESULT hr;
Lock();
if (NULL != activityThread)
hr = E_PENDING;
else
{
hr = S_OK;
if (NULL == cancelEvent)
{
cancelEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (NULL == cancelEvent)
hr = E_FAIL;
}
if (SUCCEEDED(hr))
{
DeviceActivityThreadParam param;
param.activity = this;
param.duration = duration;
param.interval = interval;
param.readyEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (NULL == param.readyEvent)
hr = E_FAIL;
else
{
DWORD threadId;
activityThread = CreateThread(NULL, 0, DeviceActivity_ActivityThreadStarter,
&param, 0, &threadId);
if (NULL == activityThread)
hr = E_FAIL;
else
WaitForSingleObject(param.readyEvent, INFINITE);
CloseHandle(param.readyEvent);
}
}
if (FAILED(hr))
Stop();
}
Unlock();
return hr;
}
HRESULT DeviceActivity::Stop()
{
HRESULT hr;
HANDLE threadHandle, eventHandle;
Lock();
threadHandle = activityThread;
eventHandle = cancelEvent;
activityThread = NULL;
cancelEvent = NULL;
Unlock();
if (NULL != threadHandle)
{
if (NULL != eventHandle)
SetEvent(eventHandle);
WaitForSingleObject(threadHandle, INFINITE);
CloseHandle(threadHandle);
hr = S_OK;
}
else
hr = S_FALSE;
if (NULL != eventHandle)
CloseHandle(eventHandle);
return hr;
}
HRESULT DeviceActivity::SetDisplayName(const wchar_t *name)
{
HRESULT hr;
Lock();
if (NULL == name && NULL == displayName)
hr = S_FALSE;
else
{
if (NULL != displayName &&
CSTR_EQUAL == CompareString(LOCALE_USER_DEFAULT, 0, name, -1, displayName, -1))
{
hr = S_FALSE;
}
else
{
wchar_t *string;
string = String_Duplicate(name);
if (NULL == string && NULL != name)
hr = E_FAIL;
else
{
String_Free(displayName);
displayName = string;
hr = S_OK;
}
}
}
Unlock();
return hr;
}
HRESULT DeviceActivity::SetStatus(const wchar_t *newStatus)
{
HRESULT hr;
if (NULL == newStatus && NULL == status)
return S_FALSE;
Lock();
if (NULL != status &&
CSTR_EQUAL == CompareString(LOCALE_USER_DEFAULT, 0, newStatus, -1, status, -1))
{
hr = S_FALSE;
}
else
{
wchar_t *string;
string = String_Duplicate(newStatus);
if (NULL == string && NULL != newStatus)
hr = E_FAIL;
else
{
String_Free(status);
status = string;
hr = S_OK;
}
}
Unlock();
return hr;
}
HRESULT DeviceActivity::SetUser(void *data)
{
Lock();
user = data;
Unlock();
return S_OK;
}
HRESULT DeviceActivity::GetUser(void **data)
{
if (NULL == data)
return E_POINTER;
Lock();
*data = user;
Unlock();
return S_OK;
}
DWORD DeviceActivity::ActivityThread(unsigned int duration, unsigned int interval)
{
DWORD waitResult, waitTime;
HANDLE cancelEventCopy;
unsigned int position;
if (interval > duration)
interval = duration;
position = 0;
Lock();
progress = 0;
if (NULL == cancelEvent ||
0 == DuplicateHandle(GetCurrentProcess(), cancelEvent, GetCurrentProcess(),
&cancelEventCopy, 0, FALSE, DUPLICATE_SAME_ACCESS))
{
cancelEventCopy = NULL;
}
Unlock();
if(NULL == cancelEventCopy)
return -3;
Lock();
if (NULL != callbackStart)
callbackStart(this);
if (NULL != callbackProgress)
callbackProgress(this, position, duration);
Unlock();
for(;;)
{
waitTime = interval;
if ((position + waitTime) > duration)
waitTime = duration - position;
waitResult = WaitForSingleObject(cancelEventCopy, waitTime);
if (WAIT_TIMEOUT == waitResult)
{
position += waitTime;
Lock();
if (duration != 0)
{
progress = 100 * position / duration;
if (progress > 100)
progress = 100;
}
else
progress = 100;
if (NULL != callbackProgress)
callbackProgress(this, position, duration);
Unlock();
if (position >= duration)
break;
}
else
break;
}
AddRef();
Lock();
if (NULL != activityThread)
{
CloseHandle(activityThread);
activityThread = NULL;
}
if (NULL != cancelEvent)
{
CloseHandle(cancelEvent);
cancelEvent = NULL;
}
if (NULL != callbackFinish)
callbackFinish(this);
Unlock();
Release();
return 0;
}
static DWORD CALLBACK
DeviceActivity_ActivityThreadStarter(void *user)
{
DeviceActivityThreadParam *param;
DeviceActivity *activity;
unsigned int duration, interval;
DWORD result;
param = (DeviceActivityThreadParam*)user;
activity = param->activity;
duration = param->duration;
interval = param->interval;
if (NULL != param->readyEvent)
SetEvent(param->readyEvent);
if (NULL != activity)
result = activity->ActivityThread(duration, interval);
else
result = -2;
return result;
}
#define CBCLASS DeviceActivity
START_DISPATCH;
CB(ADDREF, AddRef)
CB(RELEASE, Release)
CB(QUERYINTERFACE, QueryInterface)
CB(API_GETACTIVE, GetActive)
CB(API_GETCANCELABLE, GetCancelable)
CB(API_GETPROGRESS, GetProgress)
CB(API_GETDISPLAYNAME, GetDisplayName)
CB(API_GETSTATUS, GetStatus)
CB(API_CANCEL, Cancel)
END_DISPATCH;
#undef CBCLASS
@@ -0,0 +1,91 @@
#ifndef _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_ACTIVITY_HEADER
#define _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_ACTIVITY_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
typedef enum DeviceActivityFlags
{
DeviceActivityFlag_Cancelable = (1 << 0),
DeviceActivityFlag_SupportProgress = (1 << 0),
} DeviceActivityFlags;
DEFINE_ENUM_FLAG_OPERATORS(DeviceActivityFlags);
typedef void (*DeviceActivityCallback)(DeviceActivity * /*activity*/);
typedef void (*DeviceActivityProgressCallback)(DeviceActivity * /*activity*/, unsigned int /*position*/, unsigned int /*total*/);
class DeviceActivity: public ifc_deviceactivity
{
protected:
DeviceActivity(DeviceActivityFlags flags,
DeviceActivityCallback startCb,
DeviceActivityCallback finishCb,
DeviceActivityProgressCallback progressCb,
void *user);
~DeviceActivity();
public:
static HRESULT CreateInstance(DeviceActivityFlags flags,
DeviceActivityCallback startCb,
DeviceActivityCallback finishCb,
DeviceActivityProgressCallback progressCb,
void *user,
DeviceActivity **instance);
public:
/* Dispatchable */
size_t AddRef();
size_t Release();
int QueryInterface(GUID interface_guid, void **object);
/* ifc_deviceactivity */
BOOL GetActive();
BOOL GetCancelable();
HRESULT GetProgress(unsigned int *percentCompleted);
HRESULT GetDisplayName(wchar_t *buffer, size_t bufferMax);
HRESULT GetStatus(wchar_t *buffer, size_t bufferMax);
HRESULT Cancel(HWND hostWindow);
public:
void Lock();
void Unlock();
HRESULT Start(unsigned int duration, unsigned int interval);
HRESULT Stop();
HRESULT SetDisplayName(const wchar_t *displayName);
HRESULT SetStatus(const wchar_t *status);
HRESULT SetUser(void *data);
HRESULT GetUser(void **data);
protected:
DWORD ActivityThread(unsigned int duration, unsigned int interval);
friend static DWORD CALLBACK DeviceActivity_ActivityThreadStarter(void *param);
protected:
size_t ref;
DeviceActivityFlags flags;
DeviceActivityCallback callbackStart;
DeviceActivityCallback callbackFinish;
DeviceActivityProgressCallback callbackProgress;
void *user;
wchar_t *displayName;
wchar_t *status;
HANDLE activityThread;
HANDLE cancelEvent;
unsigned int progress;
CRITICAL_SECTION lock;
protected:
RECVS_DISPATCH;
};
#endif //_NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_ACTIVITY_HEADER
@@ -0,0 +1,75 @@
#include "main.h"
#include "./DeviceCommandNodeParser.h"
#include "../../xml/obj_xml.h"
DeviceCommandNodeParser::DeviceCommandNodeParser()
: reader(NULL), test(NULL)
{
}
DeviceCommandNodeParser::~DeviceCommandNodeParser()
{
End();
}
BOOL DeviceCommandNodeParser::Begin(obj_xml *xmlReader, TestSuite *testSuite)
{
if (NULL != reader || NULL != test)
return FALSE;
if (NULL == xmlReader || NULL == testSuite)
return FALSE;
reader = xmlReader;
reader->AddRef();
test = testSuite;
reader->xmlreader_registerCallback(L"testprovider\fcommands\fcommand", this);
return TRUE;
}
void DeviceCommandNodeParser::End()
{
if (NULL != reader)
{
reader->xmlreader_unregisterCallback(this);
reader->Release();
reader = NULL;
}
if (NULL != test)
test = NULL;
}
void DeviceCommandNodeParser::Event_XmlStartElement(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params)
{
elementParser.Begin(reader, params);
}
void DeviceCommandNodeParser::Event_XmlEndElement(const wchar_t *xmlpath, const wchar_t *xmltag)
{
ifc_devicecommand *result;
if (FALSE != elementParser.End(reader, &result))
{
if (NULL != test)
test->AddCommand(result);
result->Release();
}
}
void DeviceCommandNodeParser::Event_XmlError(int linenum, int errcode, const wchar_t *errstr)
{
}
#define CBCLASS DeviceCommandNodeParser
START_DISPATCH;
VCB(ONSTARTELEMENT, Event_XmlStartElement)
VCB(ONENDELEMENT, Event_XmlEndElement)
VCB(ONERROR, Event_XmlError)
END_DISPATCH;
#undef CBCLASS
@@ -0,0 +1,39 @@
#ifndef _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_COMMAND_NODE_PARSER_HEADER
#define _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_COMMAND_NODE_PARSER_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
#include "../../xml/ifc_xmlreadercallback.h"
#include "./deviceCommandParser.h"
class obj_xml;
class DeviceCommandNodeParser : public ifc_xmlreadercallback
{
public:
DeviceCommandNodeParser();
~DeviceCommandNodeParser();
public:
BOOL Begin(obj_xml *xmlReader, TestSuite *testSuite);
void End();
protected:
void Event_XmlStartElement(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params);
void Event_XmlEndElement(const wchar_t *xmlpath, const wchar_t *xmltag);
void Event_XmlError(int linenum, int errcode, const wchar_t *errstr);
protected:
obj_xml *reader;
DeviceCommandParser elementParser;
TestSuite *test;
protected:
RECVS_DISPATCH;
};
#endif //_NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_COMMAND_NODE_PARSER_HEADER
@@ -0,0 +1,192 @@
#include "main.h"
#include "./deviceCommandParser.h"
#include "../../xml/obj_xml.h"
typedef void (*COMMANDTAGCALLBACK)(DeviceCommandParser* /*self*/, ifc_devicecommandeditor* /*editor*/, const wchar_t* /*value*/);
typedef struct COMMANDTAG
{
const wchar_t *name;
BOOL multiEntry;
COMMANDTAGCALLBACK callback;
} COMMANDTAG;
static void
DeviceCommandParser_DisplayNameCb(DeviceCommandParser *self, ifc_devicecommandeditor *editor, const wchar_t *value)
{
editor->SetDisplayName(value);
}
static void
DeviceCommandParser_IconCb(DeviceCommandParser *self, ifc_devicecommandeditor *editor, const wchar_t *value)
{
ifc_deviceiconstore *iconStore;
if (SUCCEEDED(editor->GetIconStore(&iconStore)))
{
iconStore->Add(value, self->iconSize.cx, self->iconSize.cy, TRUE);
iconStore->Release();
}
}
static void
DeviceCommandParser_DescirptionCb(DeviceCommandParser *self, ifc_devicecommandeditor *editor, const wchar_t *value)
{
editor->SetDescription(value);
}
static const COMMANDTAG knownTags[COMMAND_TAG_MAX] =
{
{L"displayName", FALSE, DeviceCommandParser_DisplayNameCb},
{L"icon", TRUE, DeviceCommandParser_IconCb},
{L"description", FALSE, DeviceCommandParser_DescirptionCb},
};
DeviceCommandParser::DeviceCommandParser()
: editor(NULL)
{
}
DeviceCommandParser::~DeviceCommandParser()
{
if (NULL != editor)
editor->Release();
}
BOOL DeviceCommandParser::Begin(obj_xml *reader, ifc_xmlreaderparams *params)
{
const wchar_t *name;
ifc_devicecommand *command;
char *nameAnsi;
if (NULL != editor)
return FALSE;
if (NULL == reader || NULL == params)
return FALSE;
name = params->getItemValue(L"name");
if (NULL == name)
return FALSE;
nameAnsi = String_ToAnsi(CP_UTF8, 0, name, -1, NULL, NULL);
if (NULL == nameAnsi)
return FALSE;
if (NULL != WASABI_API_DEVICES &&
SUCCEEDED(WASABI_API_DEVICES->CreateCommand(nameAnsi, &command)))
{
if(FAILED(command->QueryInterface(IFC_DeviceCommandEditor, (void**)&editor)))
editor = NULL;
command->Release();
}
AnsiString_Free(nameAnsi);
if (NULL == editor)
return FALSE;
reader->xmlreader_registerCallback(L"testprovider\fcommands\fcommand\fdisplayName", this);
reader->xmlreader_registerCallback(L"testprovider\fcommands\fcommand\fdescription", this);
reader->xmlreader_registerCallback(L"testprovider\fcommands\fcommand\ficon", this);
ZeroMemory(hitList, sizeof(hitList));
return TRUE;
}
BOOL DeviceCommandParser::End(obj_xml *reader, ifc_devicecommand **command)
{
BOOL result;
if (NULL != reader)
reader->xmlreader_unregisterCallback(this);
if (NULL == command)
return FALSE;
if (NULL == editor)
return FALSE;
if (NULL != command)
{
if (FAILED(editor->QueryInterface(IFC_DeviceCommand, (void**)command)))
result = FALSE;
else
result = TRUE;
}
else
result = TRUE;
editor->Release();
editor = NULL;
return result;
}
void DeviceCommandParser::Event_XmlStartElement(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params)
{
elementString.Clear();
if (CSTR_EQUAL == CompareString(CSTR_INVARIANT, NORM_IGNORECASE, L"icon", -1, xmltag, -1))
{
const wchar_t *sVal;
int iVal;
sVal = params->getItemValue(L"width");
if (NULL == sVal ||
FALSE == StrToIntEx(sVal, STIF_DEFAULT, &iVal))
{
iVal = 0;
}
iconSize.cx = iVal;
sVal = params->getItemValue(L"height");
if (NULL == sVal ||
FALSE == StrToIntEx(sVal, STIF_DEFAULT, &iVal))
{
iVal = 0;
}
iconSize.cy = iVal;
}
}
void DeviceCommandParser::Event_XmlEndElement(const wchar_t *xmlpath, const wchar_t *xmltag)
{
if (NULL == editor)
return;
for (size_t i = 0; i < COMMAND_TAG_MAX; i++)
{
if (FALSE == hitList[i] &&
CSTR_EQUAL == CompareString(CSTR_INVARIANT, NORM_IGNORECASE, knownTags[i].name, -1, xmltag, -1))
{
knownTags[i].callback(this, editor, elementString.Get());
if (FALSE == knownTags[i].multiEntry)
hitList[i] = TRUE;
break;
}
}
}
void DeviceCommandParser::Event_XmlCharData(const wchar_t *xmlpath, const wchar_t *xmltag, const wchar_t *value)
{
elementString.Append(value);
}
void DeviceCommandParser::Event_XmlError(int linenum, int errcode, const wchar_t *errstr)
{
elementString.Clear();
}
#define CBCLASS DeviceCommandParser
START_DISPATCH;
VCB(ONSTARTELEMENT, Event_XmlStartElement)
VCB(ONENDELEMENT, Event_XmlEndElement)
VCB(ONCHARDATA, Event_XmlCharData)
VCB(ONERROR, Event_XmlError)
END_DISPATCH;
#undef CBCLASS
@@ -0,0 +1,47 @@
#ifndef _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_COMMAND_PARSER_HEADER
#define _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_COMMAND_PARSER_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
#include "../../xml/ifc_xmlreadercallback.h"
class obj_xml;
#define COMMAND_TAG_MAX 3
class DeviceCommandParser : public ifc_xmlreadercallback
{
public:
DeviceCommandParser();
~DeviceCommandParser();
public:
BOOL Begin(obj_xml *reader, ifc_xmlreaderparams *params);
BOOL End(obj_xml *reader, ifc_devicecommand **command);
protected:
void Event_XmlStartElement(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params);
void Event_XmlEndElement(const wchar_t *xmlpath, const wchar_t *xmltag);
void Event_XmlCharData(const wchar_t *xmlpath, const wchar_t *xmltag, const wchar_t *value);
void Event_XmlError(int linenum, int errcode, const wchar_t *errstr);
protected:
friend static void DeviceCommandParser_DisplayNameCb(DeviceCommandParser *self, ifc_devicecommandeditor *editor, const wchar_t *value);
friend static void DeviceCommandParser_IconCb(DeviceCommandParser *self, ifc_devicecommandeditor *editor, const wchar_t *value);
friend static void DeviceCommandParser_DescirptionCb(DeviceCommandParser *self, ifc_devicecommandeditor *editor, const wchar_t *value);
protected:
StringBuilder elementString;
ifc_devicecommandeditor *editor;
BOOL hitList[COMMAND_TAG_MAX];
SIZE iconSize;
protected:
RECVS_DISPATCH;
};
#endif // _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_COMMAND_PARSER_HEADER
@@ -0,0 +1,75 @@
#include "main.h"
#include "./DeviceConnectionNodeParser.h"
#include "../../xml/obj_xml.h"
DeviceConnectionNodeParser::DeviceConnectionNodeParser()
: reader(NULL), test(NULL)
{
}
DeviceConnectionNodeParser::~DeviceConnectionNodeParser()
{
End();
}
BOOL DeviceConnectionNodeParser::Begin(obj_xml *xmlReader, TestSuite *testSuite)
{
if (NULL != reader || NULL != test)
return FALSE;
if (NULL == xmlReader || NULL == testSuite)
return FALSE;
reader = xmlReader;
reader->AddRef();
test = testSuite;
reader->xmlreader_registerCallback(L"testprovider\fconnections\fconnection", this);
return TRUE;
}
void DeviceConnectionNodeParser::End()
{
if (NULL != reader)
{
reader->xmlreader_unregisterCallback(this);
reader->Release();
reader = NULL;
}
if (NULL != test)
test = NULL;
}
void DeviceConnectionNodeParser::Event_XmlStartElement(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params)
{
elementParser.Begin(reader, params);
}
void DeviceConnectionNodeParser::Event_XmlEndElement(const wchar_t *xmlpath, const wchar_t *xmltag)
{
ifc_deviceconnection *result;
if (FALSE != elementParser.End(reader, &result))
{
if (NULL != test)
test->AddConnection(result);
result->Release();
}
}
void DeviceConnectionNodeParser::Event_XmlError(int linenum, int errcode, const wchar_t *errstr)
{
}
#define CBCLASS DeviceConnectionNodeParser
START_DISPATCH;
VCB(ONSTARTELEMENT, Event_XmlStartElement)
VCB(ONENDELEMENT, Event_XmlEndElement)
VCB(ONERROR, Event_XmlError)
END_DISPATCH;
#undef CBCLASS
@@ -0,0 +1,39 @@
#ifndef _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_CONNECTION_NODE_PARSER_HEADER
#define _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_CONNECTION_NODE_PARSER_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
#include "../../xml/ifc_xmlreadercallback.h"
#include "./deviceConnectionParser.h"
class obj_xml;
class DeviceConnectionNodeParser : public ifc_xmlreadercallback
{
public:
DeviceConnectionNodeParser();
~DeviceConnectionNodeParser();
public:
BOOL Begin(obj_xml *xmlReader, TestSuite *testSuite);
void End();
protected:
void Event_XmlStartElement(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params);
void Event_XmlEndElement(const wchar_t *xmlpath, const wchar_t *xmltag);
void Event_XmlError(int linenum, int errcode, const wchar_t *errstr);
protected:
obj_xml *reader;
DeviceConnectionParser elementParser;
TestSuite *test;
protected:
RECVS_DISPATCH;
};
#endif //_NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_CONNECTION_NODE_PARSER_HEADER
@@ -0,0 +1,181 @@
#include "main.h"
#include "./deviceConnectionParser.h"
#include "../../xml/obj_xml.h"
typedef void (*CONNECTIONTAGCALLBACK)(DeviceConnectionParser* /*self*/, ifc_deviceconnectioneditor * /*editor*/, const wchar_t* /*value*/);
typedef struct CONNECTIONTAG
{
const wchar_t *name;
BOOL multiEntry;
CONNECTIONTAGCALLBACK callback;
} CONNECTIONTAG;
static void
DeviceConnectionParser_DisplayNameCb(DeviceConnectionParser *self, ifc_deviceconnectioneditor *editor, const wchar_t *value)
{
editor->SetDisplayName(value);
}
static void
DeviceConnectionParser_IconCb(DeviceConnectionParser *self, ifc_deviceconnectioneditor *editor, const wchar_t *value)
{
ifc_deviceiconstore *iconStore;
if (SUCCEEDED(editor->GetIconStore(&iconStore)))
{
iconStore->Add(value, self->iconSize.cx, self->iconSize.cy, TRUE);
iconStore->Release();
}
}
static const CONNECTIONTAG knownTags[CONNECTION_TAG_MAX] =
{
{L"displayName", FALSE, DeviceConnectionParser_DisplayNameCb},
{L"icon", TRUE, DeviceConnectionParser_IconCb},
};
DeviceConnectionParser::DeviceConnectionParser()
: editor(NULL)
{
}
DeviceConnectionParser::~DeviceConnectionParser()
{
if (NULL != editor)
editor->Release();
}
BOOL DeviceConnectionParser::Begin(obj_xml *reader, ifc_xmlreaderparams *params)
{
const wchar_t *name;
ifc_deviceconnection *connection;
char *nameAnsi;
if (NULL != editor)
return FALSE;
if (NULL == reader || NULL == params)
return FALSE;
name = params->getItemValue(L"name");
if (NULL == name)
return FALSE;
nameAnsi = String_ToAnsi(CP_UTF8, 0, name, -1, NULL, NULL);
if (NULL == nameAnsi)
return FALSE;
if (NULL != WASABI_API_DEVICES &&
SUCCEEDED(WASABI_API_DEVICES->CreateConnection(nameAnsi, &connection)))
{
if(FAILED(connection->QueryInterface(IFC_DeviceConnectionEditor, (void**)&editor)))
editor = NULL;
connection->Release();
}
AnsiString_Free(nameAnsi);
if (NULL == editor)
return FALSE;
reader->xmlreader_registerCallback(L"testprovider\fconnections\fconnection\fdisplayName", this);
reader->xmlreader_registerCallback(L"testprovider\fconnections\fconnection\ficon", this);
ZeroMemory(hitList, sizeof(hitList));
return TRUE;
}
BOOL DeviceConnectionParser::End(obj_xml *reader, ifc_deviceconnection **connection)
{
BOOL result;
if (NULL != reader)
reader->xmlreader_unregisterCallback(this);
if (NULL == editor)
return FALSE;
if (NULL != connection)
{
if (FAILED(editor->QueryInterface(IFC_DeviceConnection, (void**)connection)))
result = FALSE;
else
result = TRUE;
}
else
result = TRUE;
editor->Release();
editor = NULL;
return result;
}
void DeviceConnectionParser::Event_XmlStartElement(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params)
{
elementString.Clear();
if (CSTR_EQUAL == CompareString(CSTR_INVARIANT, NORM_IGNORECASE, L"icon", -1, xmltag, -1))
{
const wchar_t *sVal;
int iVal;
sVal = params->getItemValue(L"width");
if (NULL == sVal ||
FALSE == StrToIntEx(sVal, STIF_DEFAULT, &iVal))
{
iVal = 0;
}
iconSize.cx = iVal;
sVal = params->getItemValue(L"height");
if (NULL == sVal ||
FALSE == StrToIntEx(sVal, STIF_DEFAULT, &iVal))
{
iVal = 0;
}
iconSize.cy = iVal;
}
}
void DeviceConnectionParser::Event_XmlEndElement(const wchar_t *xmlpath, const wchar_t *xmltag)
{
if (NULL == editor)
return;
for (size_t i = 0; i < CONNECTION_TAG_MAX; i++)
{
if (FALSE == hitList[i] &&
CSTR_EQUAL == CompareString(CSTR_INVARIANT, NORM_IGNORECASE, knownTags[i].name, -1, xmltag, -1))
{
knownTags[i].callback(this, editor, elementString.Get());
if (FALSE == knownTags[i].multiEntry)
hitList[i] = TRUE;
break;
}
}
}
void DeviceConnectionParser::Event_XmlCharData(const wchar_t *xmlpath, const wchar_t *xmltag, const wchar_t *value)
{
elementString.Append(value);
}
void DeviceConnectionParser::Event_XmlError(int linenum, int errcode, const wchar_t *errstr)
{
elementString.Clear();
}
#define CBCLASS DeviceConnectionParser
START_DISPATCH;
VCB(ONSTARTELEMENT, Event_XmlStartElement)
VCB(ONENDELEMENT, Event_XmlEndElement)
VCB(ONCHARDATA, Event_XmlCharData)
VCB(ONERROR, Event_XmlError)
END_DISPATCH;
#undef CBCLASS
@@ -0,0 +1,46 @@
#ifndef _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_CONNECTION_PARSER_HEADER
#define _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_CONNECTION_PARSER_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
#include "../../xml/ifc_xmlreadercallback.h"
class obj_xml;
#define CONNECTION_TAG_MAX 2
class DeviceConnectionParser : public ifc_xmlreadercallback
{
public:
DeviceConnectionParser();
~DeviceConnectionParser();
public:
BOOL Begin(obj_xml *reader, ifc_xmlreaderparams *params);
BOOL End(obj_xml *reader, ifc_deviceconnection **connection);
protected:
void Event_XmlStartElement(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params);
void Event_XmlEndElement(const wchar_t *xmlpath, const wchar_t *xmltag);
void Event_XmlCharData(const wchar_t *xmlpath, const wchar_t *xmltag, const wchar_t *value);
void Event_XmlError(int linenum, int errcode, const wchar_t *errstr);
protected:
friend static void DeviceConnectionParser_DisplayNameCb(DeviceConnectionParser *self, ifc_deviceconnectioneditor *editor, const wchar_t *value);
friend static void DeviceConnectionParser_IconCb(DeviceConnectionParser *self, ifc_deviceconnectioneditor *editor, const wchar_t *value);
protected:
StringBuilder elementString;
ifc_deviceconnectioneditor *editor;
BOOL hitList[CONNECTION_TAG_MAX];
SIZE iconSize;
protected:
RECVS_DISPATCH;
};
#endif // _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_CONNECTION_PARSER_HEADER
@@ -0,0 +1,178 @@
#include "main.h"
#include "./deviceIconEditor.h"
#define DEVICEICONEDITOR_PROP L"NullsoftDevicesIconEditorProp"
static INT_PTR
DeviceIconEditor_DialogProc(HWND hwnd, unsigned int uMsg, WPARAM wParam, LPARAM lParam);
INT_PTR
DeviceIconEditor_Show(HWND parentWindow, DeviceIconInfo *iconInfo)
{
if (NULL == iconInfo)
return -1;
return WASABI_API_DIALOGBOXPARAMW((INT_PTR)IDD_ICON_EDITOR, parentWindow,
DeviceIconEditor_DialogProc, (LPARAM)iconInfo);
}
static void
DeviceIconEditor_UpdateInfo(HWND hwnd)
{
DeviceIconInfo *iconInfo;
HWND controlWindow;
wchar_t *string;
iconInfo = (DeviceIconInfo*)GetProp(hwnd, DEVICEICONEDITOR_PROP);
if (NULL == iconInfo)
return;
controlWindow = GetDlgItem(hwnd, IDC_EDIT_PATH);
if (NULL != controlWindow)
{
String_Free(iconInfo->path);
iconInfo->path = String_FromWindow(controlWindow);
}
controlWindow = GetDlgItem(hwnd, IDC_EDIT_WIDTH);
if (NULL != controlWindow)
{
string = String_FromWindow(controlWindow);
if (NULL == string ||
FALSE == StrToIntEx(string, STIF_DEFAULT, &iconInfo->width))
{
iconInfo->width = 0;
}
String_Free(string);
}
controlWindow = GetDlgItem(hwnd, IDC_EDIT_HEIGHT);
if (NULL != controlWindow)
{
string = String_FromWindow(controlWindow);
if (NULL == string ||
FALSE == StrToIntEx(string, STIF_DEFAULT, &iconInfo->height))
{
iconInfo->height = 0;
}
String_Free(string);
}
}
static INT_PTR
DeviceIconEditor_OnInitDialog(HWND hwnd, HWND focusWindow, LPARAM param)
{
DeviceIconInfo *iconInfo;
HWND controlWindow;
iconInfo = (DeviceIconInfo*)param;
SetProp(hwnd, DEVICEICONEDITOR_PROP, iconInfo);
if (NULL != iconInfo)
{
wchar_t buffer[64];
controlWindow = GetDlgItem(hwnd, IDC_EDIT_PATH);
if (NULL != controlWindow)
SetWindowText(controlWindow, iconInfo->path);
controlWindow = GetDlgItem(hwnd, IDC_EDIT_WIDTH);
if (NULL != controlWindow)
{
_itow_s(iconInfo->width, buffer, 10);
SetWindowText(controlWindow, buffer);
}
controlWindow = GetDlgItem(hwnd, IDC_EDIT_HEIGHT);
if (NULL != controlWindow)
{
_itow_s(iconInfo->height, buffer, 10);
SetWindowText(controlWindow, buffer);
}
}
return 0;
}
static void
DeviceIconEditor_DisplayFileOpen(HWND hwnd)
{
wchar_t buffer[MAX_PATH * 2];
OPENFILENAME ofn;
HWND controlWindow;
buffer[0] = L'\0';
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hwnd;
ofn.lpstrFilter = L"Portable Network Graphics\0" L"*.png\0"
L"\0";
ofn.lpstrFile = buffer;
ofn.nMaxFile = ARRAYSIZE(buffer);
ofn.lpstrTitle = L"Load Icon";
ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;
if (FALSE == GetOpenFileName(&ofn))
return;
controlWindow = GetDlgItem(hwnd, IDC_EDIT_PATH);
if (NULL != controlWindow)
SetWindowText(controlWindow, buffer);
}
static void
DeviceIconEditor_OnDestroy(HWND hwnd)
{
RemoveProp(hwnd, DEVICEICONEDITOR_PROP);
}
static void
DeviceIconEditor_OnCommand(HWND hwnd, INT commandId, INT eventId, HWND controlWindow)
{
switch(commandId)
{
case IDOK:
switch(eventId)
{
case BN_CLICKED:
DeviceIconEditor_UpdateInfo(hwnd);
EndDialog(hwnd, IDOK);
break;
}
break;
case IDCANCEL:
switch(eventId)
{
case BN_CLICKED:
EndDialog(hwnd, IDCANCEL);
break;
}
break;
case IDC_BUTTON_BROWSE:
switch(eventId)
{
case BN_CLICKED:
DeviceIconEditor_DisplayFileOpen(hwnd);
break;
}
break;
}
}
static INT_PTR
DeviceIconEditor_DialogProc(HWND hwnd, unsigned int uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_INITDIALOG: return DeviceIconEditor_OnInitDialog(hwnd, (HWND)wParam, lParam);
case WM_DESTROY: DeviceIconEditor_OnDestroy(hwnd); return TRUE;
case WM_COMMAND: DeviceIconEditor_OnCommand(hwnd, LOWORD(wParam), HIWORD(wParam), (HWND)lParam); return TRUE;
}
return 0;
}
@@ -0,0 +1,22 @@
#ifndef _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_ICON_EDITOR_HEADER
#define _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_ICON_EDITOR_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
typedef struct DeviceIconInfo
{
int width;
int height;
wchar_t *path;
} DeviceIconInfo;
INT_PTR
DeviceIconEditor_Show(HWND parentWindow,
DeviceIconInfo *iconInfo);
#endif //_NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_ICON_EDITOR_HEADER
@@ -0,0 +1,75 @@
#include "main.h"
#include "./DeviceNodeParser.h"
#include "../../xml/obj_xml.h"
DeviceNodeParser::DeviceNodeParser()
: reader(NULL), test(NULL)
{
}
DeviceNodeParser::~DeviceNodeParser()
{
End();
}
BOOL DeviceNodeParser::Begin(obj_xml *xmlReader, TestSuite *testSuite)
{
if (NULL != reader || NULL != test)
return FALSE;
if (NULL == xmlReader || NULL == testSuite)
return FALSE;
reader = xmlReader;
reader->AddRef();
test = testSuite;
reader->xmlreader_registerCallback(L"testprovider\fdevices\fdevice", this);
return TRUE;
}
void DeviceNodeParser::End()
{
if (NULL != reader)
{
reader->xmlreader_unregisterCallback(this);
reader->Release();
reader = NULL;
}
if (NULL != test)
test = NULL;
}
void DeviceNodeParser::Event_XmlStartElement(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params)
{
elementParser.Begin(reader, params);
}
void DeviceNodeParser::Event_XmlEndElement(const wchar_t *xmlpath, const wchar_t *xmltag)
{
Device *result;
if (FALSE != elementParser.End(reader, &result))
{
if (NULL != test)
test->AddDevice(result);
result->Release();
}
}
void DeviceNodeParser::Event_XmlError(int linenum, int errcode, const wchar_t *errstr)
{
}
#define CBCLASS DeviceNodeParser
START_DISPATCH;
VCB(ONSTARTELEMENT, Event_XmlStartElement)
VCB(ONENDELEMENT, Event_XmlEndElement)
VCB(ONERROR, Event_XmlError)
END_DISPATCH;
#undef CBCLASS
@@ -0,0 +1,39 @@
#ifndef _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_NODE_PARSER_HEADER
#define _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_NODE_PARSER_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
#include "../../xml/ifc_xmlreadercallback.h"
#include "./deviceParser.h"
class obj_xml;
class DeviceNodeParser : public ifc_xmlreadercallback
{
public:
DeviceNodeParser();
~DeviceNodeParser();
public:
BOOL Begin(obj_xml *xmlReader, TestSuite *testSuite);
void End();
protected:
void Event_XmlStartElement(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params);
void Event_XmlEndElement(const wchar_t *xmlpath, const wchar_t *xmltag);
void Event_XmlError(int linenum, int errcode, const wchar_t *errstr);
protected:
obj_xml *reader;
DeviceParser elementParser;
TestSuite *test;
protected:
RECVS_DISPATCH;
};
#endif //_NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_NODE_PARSER_HEADER
@@ -0,0 +1,306 @@
#include "main.h"
#include "./deviceParser.h"
#include "../../xml/obj_xml.h"
typedef void (*DEVICETAGCALLBACK)(DeviceParser* /*self*/, Device* /*device*/, const wchar_t* /*value*/);
typedef struct DEVICETAG
{
const wchar_t *name;
BOOL multiEntry;
DEVICETAGCALLBACK callback;
} DEVICETAG;
static void
DeviceParser_ConnectionCb(DeviceParser *self, Device *device, const wchar_t *value)
{
char *connectionAnsi;
connectionAnsi = (NULL != value) ?
String_ToAnsi(CP_UTF8, 0, value, -1, NULL, NULL) :
NULL;
device->SetConnection(connectionAnsi);
AnsiString_Free(connectionAnsi);
}
static void
DeviceParser_DisplayNameCb(DeviceParser *self, Device *device, const wchar_t *value)
{
device->SetDisplayName(value);
}
static void
DeviceParser_IconCb(DeviceParser *self, Device *device, const wchar_t *value)
{
device->AddIcon(value, self->iconSize.cx, self->iconSize.cy);
}
static void
DeviceParser_TotalSpaceCb(DeviceParser *self, Device *device, const wchar_t *value)
{
size_t size;
if (NULL == value)
size = -1;
else
{
LONGLONG lval;
if (FALSE == StrToInt64Ex(value, STIF_DEFAULT, &lval))
return;
size = (size_t)lval;
}
device->SetTotalSpace(size);
}
static void
DeviceParser_UsedSpaceCb(DeviceParser *self, Device *device, const wchar_t *value)
{
size_t size;
if (NULL == value)
size = -1;
else
{
LONGLONG lval;
if (FALSE == StrToInt64Ex(value, STIF_DEFAULT, &lval))
return;
size = (size_t)lval;
}
device->SetUsedSpace(size);
}
static void
DeviceParser_HiddenCb(DeviceParser *self, Device *device, const wchar_t *value)
{
int hidden;
if (FALSE != StrToIntEx(value, STIF_DEFAULT, &hidden))
device->SetHidden(0 != hidden);
}
static void
DeviceParser_CommandCb(DeviceParser *self, Device *device, const wchar_t *value)
{
char *command;
if (FALSE != IS_STRING_EMPTY(value))
return;
command = String_ToAnsi(CP_UTF8, 0, value, -1, NULL, NULL);
if (NULL != command)
{
device->AddCommand(command, self->commandFlags);
AnsiString_Free(command);
}
}
static void
DeviceParser_ModelCb(DeviceParser *self, Device *device, const wchar_t *value)
{
device->SetModel(value);
}
static void
DeviceParser_StatusCb(DeviceParser *self, Device *device, const wchar_t *value)
{
device->SetStatus(value);
}
static const DEVICETAG knownTags[DEVICE_TAG_MAX] =
{
{L"connection", FALSE, DeviceParser_ConnectionCb},
{L"displayName", FALSE, DeviceParser_DisplayNameCb},
{L"icon", TRUE, DeviceParser_IconCb},
{L"totalSpace", FALSE, DeviceParser_TotalSpaceCb},
{L"usedSpace", FALSE, DeviceParser_UsedSpaceCb},
{L"hidden", FALSE, DeviceParser_HiddenCb},
{L"command", TRUE, DeviceParser_CommandCb},
{L"model", FALSE, DeviceParser_ModelCb},
{L"status", FALSE, DeviceParser_StatusCb},
};
DeviceParser::DeviceParser()
: device(NULL)
{
}
DeviceParser::~DeviceParser()
{
if (NULL != device)
device->Release();
}
BOOL DeviceParser::Begin(obj_xml *reader, ifc_xmlreaderparams *params)
{
const wchar_t *value;
char *nameAnsi, *typeAnsi;
if (NULL != device)
return FALSE;
if (NULL == reader || NULL == params)
return FALSE;
value = params->getItemValue(L"name");
nameAnsi = (NULL != value) ? String_ToAnsi(CP_UTF8, 0, value, -1, NULL, NULL) : NULL;
value = params->getItemValue(L"type");
typeAnsi = (NULL != value) ? String_ToAnsi(CP_UTF8, 0, value, -1, NULL, NULL) : NULL;
if (NULL == nameAnsi ||
NULL == typeAnsi ||
FAILED(Device::CreateInstance(nameAnsi, typeAnsi, NULL, &device)))
{
device = NULL;
}
AnsiString_Free(nameAnsi);
AnsiString_Free(typeAnsi);
if (NULL == device)
return FALSE;
reader->xmlreader_registerCallback(L"testprovider\fdevices\fdevice\fconnection", this);
reader->xmlreader_registerCallback(L"testprovider\fdevices\fdevice\fdisplayName", this);
reader->xmlreader_registerCallback(L"testprovider\fdevices\fdevice\ficon", this);
reader->xmlreader_registerCallback(L"testprovider\fdevices\fdevice\ftotalSpace", this);
reader->xmlreader_registerCallback(L"testprovider\fdevices\fdevice\fusedSpace", this);
reader->xmlreader_registerCallback(L"testprovider\fdevices\fdevice\fhidden", this);
reader->xmlreader_registerCallback(L"testprovider\fdevices\fdevice\fcommand", this);
reader->xmlreader_registerCallback(L"testprovider\fdevices\fdevice\fmodel", this);
reader->xmlreader_registerCallback(L"testprovider\fdevices\fdevice\fstatus", this);
ZeroMemory(hitList, sizeof(hitList));
return TRUE;
}
BOOL DeviceParser::End(obj_xml *reader, Device **result)
{
if (NULL != reader)
reader->xmlreader_unregisterCallback(this);
if (NULL == device)
return FALSE;
if (NULL != result)
{
*result = device;
device->AddRef();
}
device->Release();
device = NULL;
return TRUE;
}
void DeviceParser::Event_XmlStartElement(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params)
{
elementString.Clear();
if (CSTR_EQUAL == CompareString(CSTR_INVARIANT, NORM_IGNORECASE, L"icon", -1, xmltag, -1))
{
const wchar_t *sVal;
int iVal;
sVal = params->getItemValue(L"width");
if (NULL == sVal ||
FALSE == StrToIntEx(sVal, STIF_DEFAULT, &iVal))
{
iVal = 0;
}
iconSize.cx = iVal;
sVal = params->getItemValue(L"height");
if (NULL == sVal ||
FALSE == StrToIntEx(sVal, STIF_DEFAULT, &iVal))
{
iVal = 0;
}
iconSize.cy = iVal;
}
else if (CSTR_EQUAL == CompareString(CSTR_INVARIANT, NORM_IGNORECASE, L"command", -1, xmltag, -1))
{
const wchar_t *sVal;
int iVal;
commandFlags = DeviceCommandFlag_None;
sVal = params->getItemValue(L"primary");
if (FALSE == IS_STRING_EMPTY(sVal) &&
FALSE != StrToIntEx(sVal, STIF_DEFAULT, &iVal) &&
0 != iVal)
{
commandFlags |= DeviceCommandFlag_Primary;
}
sVal = params->getItemValue(L"group");
if (FALSE == IS_STRING_EMPTY(sVal) &&
FALSE != StrToIntEx(sVal, STIF_DEFAULT, &iVal) &&
0 != iVal)
{
commandFlags |= DeviceCommandFlag_Group;
}
sVal = params->getItemValue(L"disabled");
if (FALSE == IS_STRING_EMPTY(sVal) &&
FALSE != StrToIntEx(sVal, STIF_DEFAULT, &iVal) &&
0 != iVal)
{
commandFlags |= DeviceCommandFlag_Disabled;
}
sVal = params->getItemValue(L"hidden");
if (FALSE == IS_STRING_EMPTY(sVal) &&
FALSE != StrToIntEx(sVal, STIF_DEFAULT, &iVal) &&
0 != iVal)
{
commandFlags |= DeviceCommandFlag_Hidden;
}
}
}
void DeviceParser::Event_XmlEndElement(const wchar_t *xmlpath, const wchar_t *xmltag)
{
if (NULL == device)
return;
for (size_t i = 0; i < DEVICE_TAG_MAX; i++)
{
if (FALSE == hitList[i] &&
CSTR_EQUAL == CompareString(CSTR_INVARIANT, NORM_IGNORECASE, knownTags[i].name, -1, xmltag, -1))
{
knownTags[i].callback(this, device, elementString.Get());
if (FALSE == knownTags[i].multiEntry)
hitList[i] = TRUE;
break;
}
}
}
void DeviceParser::Event_XmlCharData(const wchar_t *xmlpath, const wchar_t *xmltag, const wchar_t *value)
{
elementString.Append(value);
}
void DeviceParser::Event_XmlError(int linenum, int errcode, const wchar_t *errstr)
{
elementString.Clear();
}
#define CBCLASS DeviceParser
START_DISPATCH;
VCB(ONSTARTELEMENT, Event_XmlStartElement)
VCB(ONENDELEMENT, Event_XmlEndElement)
VCB(ONCHARDATA, Event_XmlCharData)
VCB(ONERROR, Event_XmlError)
END_DISPATCH;
#undef CBCLASS
@@ -0,0 +1,54 @@
#ifndef _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_PARSER_HEADER
#define _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_PARSER_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
#include "../../xml/ifc_xmlreadercallback.h"
#include "./device.h"
class obj_xml;
#define DEVICE_TAG_MAX 9
class DeviceParser : public ifc_xmlreadercallback
{
public:
DeviceParser();
~DeviceParser();
public:
BOOL Begin(obj_xml *reader, ifc_xmlreaderparams *params);
BOOL End(obj_xml *reader, Device **result);
protected:
void Event_XmlStartElement(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params);
void Event_XmlEndElement(const wchar_t *xmlpath, const wchar_t *xmltag);
void Event_XmlCharData(const wchar_t *xmlpath, const wchar_t *xmltag, const wchar_t *value);
void Event_XmlError(int linenum, int errcode, const wchar_t *errstr);
protected:
friend static void DeviceParser_IconCb(DeviceParser *self, Device *device, const wchar_t *value);
friend static void DeviceParser_ConnectionCb(DeviceParser *self, Device *device, const wchar_t *value);
friend static void DeviceParser_DisplayNameCb(DeviceParser *self, Device *device, const wchar_t *value);
friend static void DeviceParser_TotalSpaceCb(DeviceParser *self, Device *device, const wchar_t *value);
friend static void DeviceParser_UsedSpaceCb(DeviceParser *self, Device *device, const wchar_t *value);
friend static void DeviceParser_HiddenCb(DeviceParser *self, Device *device, const wchar_t *value);
friend static void DeviceParser_CommandCb(DeviceParser *self, Device *device, const wchar_t *value);
friend static void DeviceParser_ModelCb(DeviceParser *self, Device *device, const wchar_t *value);
friend static void DeviceParser_StatusCb(DeviceParser *self, Device *device, const wchar_t *value);
protected:
StringBuilder elementString;
Device *device;
BOOL hitList[DEVICE_TAG_MAX];
SIZE iconSize;
DeviceCommandFlags commandFlags;
protected:
RECVS_DISPATCH;
};
#endif // _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_PARSER_HEADER
@@ -0,0 +1,75 @@
#include "main.h"
#include "./DeviceTypeNodeParser.h"
#include "../../xml/obj_xml.h"
DeviceTypeNodeParser::DeviceTypeNodeParser()
: reader(NULL), test(NULL)
{
}
DeviceTypeNodeParser::~DeviceTypeNodeParser()
{
End();
}
BOOL DeviceTypeNodeParser::Begin(obj_xml *xmlReader, TestSuite *testSuite)
{
if (NULL != reader || NULL != test)
return FALSE;
if (NULL == xmlReader || NULL == testSuite)
return FALSE;
reader = xmlReader;
reader->AddRef();
test = testSuite;
reader->xmlreader_registerCallback(L"testprovider\ftypes\ftype", this);
return TRUE;
}
void DeviceTypeNodeParser::End()
{
if (NULL != reader)
{
reader->xmlreader_unregisterCallback(this);
reader->Release();
reader = NULL;
}
if (NULL != test)
test = NULL;
}
void DeviceTypeNodeParser::Event_XmlStartElement(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params)
{
elementParser.Begin(reader, params);
}
void DeviceTypeNodeParser::Event_XmlEndElement(const wchar_t *xmlpath, const wchar_t *xmltag)
{
ifc_devicetype *result;
if (FALSE != elementParser.End(reader, &result))
{
if (NULL != test)
test->AddType(result);
result->Release();
}
}
void DeviceTypeNodeParser::Event_XmlError(int linenum, int errcode, const wchar_t *errstr)
{
}
#define CBCLASS DeviceTypeNodeParser
START_DISPATCH;
VCB(ONSTARTELEMENT, Event_XmlStartElement)
VCB(ONENDELEMENT, Event_XmlEndElement)
VCB(ONERROR, Event_XmlError)
END_DISPATCH;
#undef CBCLASS
@@ -0,0 +1,39 @@
#ifndef _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_TYPE_NODE_PARSER_HEADER
#define _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_TYPE_NODE_PARSER_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
#include "../../xml/ifc_xmlreadercallback.h"
#include "./deviceTypeParser.h"
class obj_xml;
class DeviceTypeNodeParser : public ifc_xmlreadercallback
{
public:
DeviceTypeNodeParser();
~DeviceTypeNodeParser();
public:
BOOL Begin(obj_xml *xmlReader, TestSuite *testSuite);
void End();
protected:
void Event_XmlStartElement(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params);
void Event_XmlEndElement(const wchar_t *xmlpath, const wchar_t *xmltag);
void Event_XmlError(int linenum, int errcode, const wchar_t *errstr);
protected:
obj_xml *reader;
DeviceTypeParser elementParser;
TestSuite *test;
protected:
RECVS_DISPATCH;
};
#endif //_NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_TYPE_NODE_PARSER_HEADER
@@ -0,0 +1,182 @@
#include "main.h"
#include "./deviceTypeParser.h"
#include "../../xml/obj_xml.h"
typedef void (*TYPETAGCALLBACK)(DeviceTypeParser* /*self*/, ifc_devicetypeeditor* /*editor*/, const wchar_t* /*value*/);
typedef struct TYPETAG
{
const wchar_t *name;
BOOL multiEntry;
TYPETAGCALLBACK callback;
} TYPETAG;
static void
DeviceTypeParser_DisplayNameCb(DeviceTypeParser *self, ifc_devicetypeeditor *editor, const wchar_t *value)
{
editor->SetDisplayName(value);
}
static void
DeviceTypeParser_IconCb(DeviceTypeParser *self, ifc_devicetypeeditor *editor, const wchar_t *value)
{
ifc_deviceiconstore *iconStore;
if (SUCCEEDED(editor->GetIconStore(&iconStore)))
{
iconStore->Add(value, self->iconSize.cx, self->iconSize.cy, TRUE);
iconStore->Release();
}
}
static const TYPETAG knownTags[TYPE_TAG_MAX] =
{
{L"displayName", FALSE, DeviceTypeParser_DisplayNameCb},
{L"icon", TRUE, DeviceTypeParser_IconCb},
};
DeviceTypeParser::DeviceTypeParser()
: editor(NULL)
{
}
DeviceTypeParser::~DeviceTypeParser()
{
if (NULL != editor)
editor->Release();
}
BOOL DeviceTypeParser::Begin(obj_xml *reader, ifc_xmlreaderparams *params)
{
const wchar_t *name;
ifc_devicetype *type;
char *nameAnsi;
if (NULL != editor)
return FALSE;
if (NULL == reader || NULL == params)
return FALSE;
name = params->getItemValue(L"name");
if (NULL == name)
return FALSE;
nameAnsi = String_ToAnsi(CP_UTF8, 0, name, -1, NULL, NULL);
if (NULL == nameAnsi)
return FALSE;
if (NULL != WASABI_API_DEVICES &&
SUCCEEDED(WASABI_API_DEVICES->CreateType(nameAnsi, &type)))
{
if(FAILED(type->QueryInterface(IFC_DeviceTypeEditor, (void**)&editor)))
editor = NULL;
type->Release();
}
AnsiString_Free(nameAnsi);
if (NULL == editor)
return FALSE;
reader->xmlreader_registerCallback(L"testprovider\ftypes\ftype\fdisplayName", this);
reader->xmlreader_registerCallback(L"testprovider\ftypes\ftype\ficon", this);
ZeroMemory(hitList, sizeof(hitList));
return TRUE;
}
BOOL DeviceTypeParser::End(obj_xml *reader, ifc_devicetype **deviceType)
{
BOOL result;
if (NULL != reader)
reader->xmlreader_unregisterCallback(this);
if (NULL == editor)
return FALSE;
if (NULL != deviceType)
{
if (FAILED(editor->QueryInterface(IFC_DeviceType, (void**)deviceType)))
result = FALSE;
else
result = TRUE;
}
else
result = TRUE;
editor->Release();
editor = NULL;
return result;
}
void DeviceTypeParser::Event_XmlStartElement(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params)
{
elementString.Clear();
if (CSTR_EQUAL == CompareString(CSTR_INVARIANT, NORM_IGNORECASE, L"icon", -1, xmltag, -1))
{
const wchar_t *sVal;
int iVal;
sVal = params->getItemValue(L"width");
if (NULL == sVal ||
FALSE == StrToIntEx(sVal, STIF_DEFAULT, &iVal))
{
iVal = 0;
}
iconSize.cx = iVal;
sVal = params->getItemValue(L"height");
if (NULL == sVal ||
FALSE == StrToIntEx(sVal, STIF_DEFAULT, &iVal))
{
iVal = 0;
}
iconSize.cy = iVal;
}
}
void DeviceTypeParser::Event_XmlEndElement(const wchar_t *xmlpath, const wchar_t *xmltag)
{
if (NULL == editor)
return;
for (size_t i = 0; i < TYPE_TAG_MAX; i++)
{
if (FALSE == hitList[i] &&
CSTR_EQUAL == CompareString(CSTR_INVARIANT, NORM_IGNORECASE, knownTags[i].name, -1, xmltag, -1))
{
knownTags[i].callback(this, editor, elementString.Get());
if (FALSE == knownTags[i].multiEntry)
hitList[i] = TRUE;
break;
}
}
}
void DeviceTypeParser::Event_XmlCharData(const wchar_t *xmlpath, const wchar_t *xmltag, const wchar_t *value)
{
elementString.Append(value);
}
void DeviceTypeParser::Event_XmlError(int linenum, int errcode, const wchar_t *errstr)
{
elementString.Clear();
}
#define CBCLASS DeviceTypeParser
START_DISPATCH;
VCB(ONSTARTELEMENT, Event_XmlStartElement)
VCB(ONENDELEMENT, Event_XmlEndElement)
VCB(ONCHARDATA, Event_XmlCharData)
VCB(ONERROR, Event_XmlError)
END_DISPATCH;
#undef CBCLASS
@@ -0,0 +1,46 @@
#ifndef _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_TYPE_PARSER_HEADER
#define _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_TYPE_PARSER_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
#include "../../xml/ifc_xmlreadercallback.h"
class obj_xml;
#define TYPE_TAG_MAX 2
class DeviceTypeParser : public ifc_xmlreadercallback
{
public:
DeviceTypeParser();
~DeviceTypeParser();
public:
BOOL Begin(obj_xml *reader, ifc_xmlreaderparams *params);
BOOL End(obj_xml *reader, ifc_devicetype **deviceType);
protected:
void Event_XmlStartElement(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params);
void Event_XmlEndElement(const wchar_t *xmlpath, const wchar_t *xmltag);
void Event_XmlCharData(const wchar_t *xmlpath, const wchar_t *xmltag, const wchar_t *value);
void Event_XmlError(int linenum, int errcode, const wchar_t *errstr);
protected:
friend static void DeviceTypeParser_DisplayNameCb(DeviceTypeParser *self, ifc_devicetypeeditor *editor, const wchar_t *value);
friend static void DeviceTypeParser_IconCb(DeviceTypeParser *self, ifc_devicetypeeditor *editor, const wchar_t *value);
protected:
StringBuilder elementString;
ifc_devicetypeeditor *editor;
BOOL hitList[TYPE_TAG_MAX];
SIZE iconSize;
protected:
RECVS_DISPATCH;
};
#endif // _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_TYPE_PARSER_HEADER
@@ -0,0 +1,994 @@
#include "main.h"
#include "./deviceView.h"
#include <wincodec.h>
#include <commctrl.h>
#include <strsafe.h>
#include <vector>
#include <algorithm>
#define DEVICEVIEW_PROP L"NullsoftDevicesViewProp"
static ATOM DEVICEVIEW_ATOM = 0;
typedef struct DeviceView
{
Device *device;
} DeviceView;
typedef std::vector<DeviceIconInfo*> DeviceIconInfoList;
static INT_PTR
DeviceView_DialogProc(HWND hwnd, unsigned int uMsg, WPARAM wParam, LPARAM lParam);
#define DEVICEVIEW(_hwnd) ((DeviceView*)GetPropW((_hwnd), MAKEINTATOM(DEVICEVIEW_ATOM)))
#define DEVICEVIEW_RET_VOID(_view, _hwnd) { (_view) = DEVICEVIEW((_hwnd)); if (NULL == (_view)) return; }
#define DEVICEVIEW_RET_VAL(_view, _hwnd, _error) { (_view) = DEVICEVIEW((_hwnd)); if (NULL == (_view)) return (_error); }
static HBITMAP
DeviceView_HBitmapFromWicSource(IWICBitmapSource *wicSource)
{
HRESULT hr;
HBITMAP bitmap;
BITMAPINFO bitmapInfo;
unsigned int width, height;
void *pixelData = NULL;
HDC windowDC;
unsigned int strideSize, imageSize;
if (NULL == wicSource)
return NULL;
hr = wicSource->GetSize(&width, &height);
if (FAILED(hr))
return NULL;
ZeroMemory(&bitmapInfo, sizeof(bitmapInfo));
bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bitmapInfo.bmiHeader.biWidth = width;
bitmapInfo.bmiHeader.biHeight = -(LONG)height;
bitmapInfo.bmiHeader.biPlanes = 1;
bitmapInfo.bmiHeader.biBitCount = 32;
bitmapInfo.bmiHeader.biCompression = BI_RGB;
windowDC = GetDCEx(NULL, NULL, DCX_WINDOW | DCX_CACHE);
bitmap = CreateDIBSection(windowDC, &bitmapInfo, DIB_RGB_COLORS, &pixelData, NULL, 0);
if (NULL != windowDC)
ReleaseDC(NULL, windowDC);
if (NULL == bitmap)
return NULL;
hr = UIntMult(width, sizeof(DWORD), &strideSize);
if (SUCCEEDED(hr))
{
hr = UIntMult(strideSize, height, &imageSize);
if (SUCCEEDED(hr))
hr = wicSource->CopyPixels(NULL, strideSize, imageSize, (BYTE*)pixelData);
}
if (FAILED(hr))
{
DeleteObject(bitmap);
bitmap = NULL;
}
return bitmap;
}
static HBITMAP
DeviceView_LoadIcon(const wchar_t *path)
{
IWICImagingFactory *wicFactory;
IWICBitmapDecoder *wicDecoder;
HRESULT hr;
HBITMAP bitmap;
hr = CoCreateInstance(CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
IID_PPV_ARGS(&wicFactory));
if (FAILED(hr))
return NULL;
bitmap = NULL;
hr = wicFactory->CreateDecoderFromFilename(path, NULL, GENERIC_READ,
WICDecodeMetadataCacheOnDemand, &wicDecoder);
if (SUCCEEDED(hr))
{
IWICBitmapFrameDecode *wicFrame;
hr = wicDecoder->GetFrame(0, &wicFrame);
if(SUCCEEDED(hr))
{
IWICBitmapSource *wicSource;
hr = wicFrame->QueryInterface(IID_IWICBitmapSource,
reinterpret_cast<void **>(&wicSource));
if (SUCCEEDED(hr))
{
WICPixelFormatGUID pixelFormat;
hr = wicSource->GetPixelFormat(&pixelFormat);
if (FAILED(hr) ||
(GUID_WICPixelFormat32bppPBGRA != pixelFormat &&
GUID_WICPixelFormat32bppBGR != pixelFormat &&
GUID_WICPixelFormat32bppBGRA != pixelFormat &&
GUID_WICPixelFormat32bppRGBA != pixelFormat &&
GUID_WICPixelFormat32bppPRGBA != pixelFormat))
{
// try to convert
IWICFormatConverter *wicConverter;
hr = wicFactory->CreateFormatConverter(&wicConverter);
if (SUCCEEDED(hr))
{
hr = wicConverter->Initialize(wicSource, GUID_WICPixelFormat32bppPBGRA,
WICBitmapDitherTypeNone, NULL, 0.f, WICBitmapPaletteTypeCustom);
if (SUCCEEDED(hr))
{
IWICBitmapSource *wicConvertedSource;
hr = wicConverter->QueryInterface(IID_IWICBitmapSource,
reinterpret_cast<void **>(&wicConvertedSource));
if (SUCCEEDED(hr))
{
wicSource->Release();
wicSource = wicConvertedSource;
}
}
wicConverter->Release();
}
}
if (SUCCEEDED(hr))
bitmap = DeviceView_HBitmapFromWicSource(wicSource);
wicSource->Release();
}
wicFrame->Release();
}
wicDecoder->Release();
}
wicFactory->Release();
return bitmap;
}
HWND
DeviceView_CreateWindow(HWND parentWindow, Device *device)
{
HWND hwnd;
if (NULL == device)
return NULL;
if (0 == DEVICEVIEW_ATOM)
{
DEVICEVIEW_ATOM = GlobalAddAtom(DEVICEVIEW_PROP);
if (0 == DEVICEVIEW_ATOM)
return NULL;
}
hwnd = WASABI_API_CREATEDIALOGPARAMW((INT_PTR)IDD_DEVICE_VIEW, parentWindow,
DeviceView_DialogProc, (LPARAM)device);
return hwnd;
}
static void
DeviceView_InitCapacity(HWND hwnd)
{
DeviceView *self;
HWND controlWindow;
uint64_t totalSpace, usedSpace;
DEVICEVIEW_RET_VOID(self, hwnd);
if (NULL != self->device)
{
if (FAILED(self->device->GetTotalSpace(&totalSpace)))
totalSpace = 0;
if (FAILED(self->device->GetUsedSpace(&usedSpace)))
usedSpace = 0;
}
else
{
totalSpace = 0;
usedSpace = 0;
}
controlWindow = GetDlgItem(hwnd, IDC_SPIN_TOTALSPACE);
if (NULL != controlWindow)
{
SendMessage(controlWindow, UDM_SETRANGE32, (WPARAM)0, (LPARAM)0xFFFFFF);
SendMessage(controlWindow, UDM_SETPOS32, (WPARAM)0, (LPARAM)totalSpace);
}
controlWindow = GetDlgItem(hwnd, IDC_SPIN_USEDSPACE);
if (NULL != controlWindow)
{
SendMessage(controlWindow, UDM_SETRANGE32, (WPARAM)0, (LPARAM)totalSpace);
SendMessage(controlWindow, UDM_SETPOS32, (WPARAM)0, (LPARAM)usedSpace);
}
}
static int
DeviceView_CompareDeviceIconInfo(const void *elem1, const void *elem2)
{
DeviceIconInfo *info1;
DeviceIconInfo *info2;
info1 = *((DeviceIconInfo**)elem1);
info2 = *((DeviceIconInfo**)elem2);
if (NULL == info1 || NULL == info2)
return (int)(info1 - info2);
if (info1->width != info2->width)
return (int)(info1->width - info2->width);
if (info1->height != info2->height)
return (int)(info1->height - info2->height);
if (NULL == info1->path || NULL == info2->path)
return (int)(info1->path - info2->path);
return CompareString(CSTR_INVARIANT, NORM_IGNORECASE, info1->path, -1, info2->path, -1) - 2;
}
static int
DeviceView_CompareDeviceIconInfo_V2(const void* elem1, const void* elem2)
{
return DeviceView_CompareDeviceIconInfo(elem1, elem2) < 0;
}
static BOOL
DeviceView_EnumerateIcons(const wchar_t *path, unsigned int width, unsigned int height, void *user)
{
DeviceIconInfo *info;
DeviceIconInfoList *list = (DeviceIconInfoList*)user;
if( NULL == list)
return FALSE;
info = (DeviceIconInfo*)malloc(sizeof(DeviceIconInfo));
if (NULL != info)
{
info->height = height;
info->width = width;
info->path = String_Duplicate(path);
list->push_back(info);
}
return TRUE;
}
static void
DeviceView_DestroyIcons(HWND hwnd)
{
HWND controlWindow;
int count, index;
DeviceIconInfo *info;
controlWindow = GetDlgItem(hwnd, IDC_COMBO_ICONS);
if (NULL == controlWindow)
return;
count = (int)SendMessage(controlWindow, CB_GETCOUNT, 0, 0L);
for(index = 0; index < count; index++)
{
info = (DeviceIconInfo*)SendMessage(controlWindow, CB_GETITEMDATA, index, 0L);
if (CB_ERR != (INT_PTR)info)
{
String_Free(info->path);
free(info);
}
}
SendMessage(controlWindow, CB_RESETCONTENT, 0, 0L);
controlWindow = GetDlgItem(hwnd, IDC_STATIC_PREVIEWICON);
if (NULL != controlWindow)
{
HBITMAP bitmap;
bitmap = (HBITMAP)SendMessage(controlWindow, STM_GETIMAGE, IMAGE_BITMAP, 0L);
if(NULL != bitmap)
DeleteObject(bitmap);
}
}
static void
DeviceView_InitIcons(HWND hwnd, const wchar_t *selectPath)
{
DeviceView *self;
DeviceIconInfoList list;
HWND controlWindow;
wchar_t buffer[2048];
DEVICEVIEW_RET_VOID(self, hwnd);
DeviceView_DestroyIcons(hwnd);
controlWindow = GetDlgItem(hwnd, IDC_COMBO_ICONS);
if (NULL != controlWindow)
{
size_t index, count;
int iItem, iSelect;
DeviceIconInfo *info;
if (NULL != self->device)
{
self->device->EnumerateIcons(DeviceView_EnumerateIcons, &list);
}
count = list.size();
//qsort(list.begin(), count, sizeof(DeviceIconInfo**), DeviceView_CompareDeviceIconInfo);
std::sort(list.begin(), list.end(), DeviceView_CompareDeviceIconInfo_V2);
iSelect = 0;
for(index = 0; index < count; index++)
{
info = list[index];
if (1 == info->width && 1 == info->height)
{
StringCchPrintf(buffer, ARRAYSIZE(buffer), L"%s",
info->path);
}
else
{
StringCchPrintf(buffer, ARRAYSIZE(buffer), L"[%dx%d] - %s",
info->width, info->height, info->path);
}
iItem = (int)SendMessage(controlWindow, CB_ADDSTRING, 0, (LPARAM)buffer);
if (CB_ERR != iItem)
{
if (CB_ERR == (int)SendMessage(controlWindow, CB_SETITEMDATA, index, (LPARAM)info))
{
SendMessage(controlWindow, CB_DELETESTRING, index, 0L);
iItem = CB_ERR;
}
}
if (CB_ERR == iItem)
{
free(info);
}
else if (NULL != selectPath &&
CSTR_EQUAL == CompareString(CSTR_INVARIANT, NORM_IGNORECASE,
info->path, -1, selectPath, -1))
{
iSelect = iItem;
}
}
iItem = (int)SendMessage(controlWindow, CB_GETCOUNT, 0, 0L);
if (CB_ERR == iItem)
iItem = 0;
EnableWindow(GetDlgItem(hwnd, IDC_BUTTON_EDITICON), (0 != iItem));
EnableWindow(GetDlgItem(hwnd, IDC_BUTTON_REMOVEICON),(0 != iItem));
SendMessage(controlWindow, CB_SETCURSEL, iSelect, 0L);
PostMessage(hwnd, WM_COMMAND, MAKEWPARAM(IDC_COMBO_ICONS, CBN_SELENDOK), (LPARAM)controlWindow);
}
}
static void
DeviceView_NewIcon(HWND hwnd)
{
DeviceView *self;
DeviceIconInfo info;
INT_PTR result;
DEVICEVIEW_RET_VOID(self, hwnd);
ZeroMemory(&info, sizeof(info));
result = DeviceIconEditor_Show(hwnd, &info);
if (IDOK == result)
{
if (NULL != self->device &&
SUCCEEDED(self->device->AddIcon(info.path, info.width, info.height)))
{
DeviceView_InitIcons(hwnd, info.path);
}
String_Free(info.path);
}
}
static void
DeviceView_RemoveIcon(HWND hwnd)
{
DeviceView *self;
DeviceIconInfo *info;
int index, count;
HWND controlWindow;
DEVICEVIEW_RET_VOID(self, hwnd);
controlWindow = GetDlgItem(hwnd, IDC_COMBO_ICONS);
if (NULL == controlWindow)
return;
index = (int)SendMessage(controlWindow, CB_GETCURSEL, 0, 0L);
if (CB_ERR == index)
return;
info = (DeviceIconInfo*)SendMessage(controlWindow, CB_GETITEMDATA, index, 0L);
if (CB_ERR != (INT_PTR)info)
{
if (NULL != self->device)
self->device->RemoveIcon(info->width, info->height);
String_Free(info->path);
free(info);
}
SendMessage(controlWindow, CB_DELETESTRING, index, 0L);
count = (int)SendMessage(controlWindow, CB_GETCOUNT, 0, 0L);
if (count > 0)
{
if (index > count)
index = count - 1;
SendMessage(controlWindow, CB_SETCURSEL, index, 0L);
}
else
{
SendMessage(controlWindow, CB_SETCURSEL, -1, 0L);
EnableWindow(GetDlgItem(hwnd, IDC_BUTTON_EDITICON),FALSE);
EnableWindow(GetDlgItem(hwnd, IDC_BUTTON_REMOVEICON),FALSE);
}
PostMessage(hwnd, WM_COMMAND, MAKEWPARAM(IDC_COMBO_ICONS, CBN_SELENDOK), (LPARAM)controlWindow);
UpdateWindow(controlWindow);
}
static void
DeviceView_EditIcon(HWND hwnd)
{
DeviceView *self;
DeviceIconInfo *info;
int index;
unsigned int width, height;
HWND controlWindow;
INT_PTR result;
DEVICEVIEW_RET_VOID(self, hwnd);
controlWindow = GetDlgItem(hwnd, IDC_COMBO_ICONS);
if (NULL == controlWindow)
return;
index = (int)SendMessage(controlWindow, CB_GETCURSEL, 0, 0L);
if (CB_ERR == index)
return;
info = (DeviceIconInfo*)SendMessage(controlWindow, CB_GETITEMDATA, index, 0L);
if (CB_ERR == (INT_PTR)info)
return;
width = info->width;
height = info->height;
result = DeviceIconEditor_Show(hwnd, info);
if (IDOK == result)
{
if (NULL != self->device)
{
self->device->RemoveIcon(width, height);
self->device->AddIcon(info->path, info->width, info->height);
DeviceView_InitIcons(hwnd, info->path);
}
}
UpdateWindow(controlWindow);
}
static void
DeviceView_InitView(HWND hwnd)
{
DeviceView *self;
HWND controlWindow;
wchar_t buffer[1024];
DEVICEVIEW_RET_VOID(self, hwnd);
controlWindow = GetDlgItem(hwnd, IDC_EDIT_NAME);
if (NULL != controlWindow)
{
if (NULL == self->device ||
0 == MultiByteToWideChar(CP_UTF8, 0, self->device->GetName(), -1, buffer, ARRAYSIZE(buffer)))
{
StringCchCopy(buffer, ARRAYSIZE(buffer), L"<unknown>");
}
SetWindowText(controlWindow, buffer);
}
controlWindow = GetDlgItem(hwnd, IDC_EDIT_TITLE);
if (NULL != controlWindow)
{
if (NULL == self->device ||
FAILED(self->device->GetDisplayName(buffer, ARRAYSIZE(buffer))))
{
StringCchCopy(buffer, ARRAYSIZE(buffer), L"<unknown>");
}
SetWindowText(controlWindow, buffer);
}
controlWindow = GetDlgItem(hwnd, IDC_EDIT_TYPE);
if (NULL != controlWindow)
{
buffer[0] = L'\0';
if (NULL != self->device)
{
const char *typeName;
ifc_devicetype *type;
typeName = self->device->GetType();
if (NULL != WASABI_API_DEVICES &&
S_OK == WASABI_API_DEVICES->TypeFind(typeName, &type))
{
if (FAILED(type->GetDisplayName(buffer, ARRAYSIZE(buffer))))
buffer[0] = L'\0';
type->Release();
}
if (L'\0' == *buffer)
MultiByteToWideChar(CP_UTF8, 0, typeName, -1, buffer, ARRAYSIZE(buffer));
}
if (L'\0' == *buffer)
StringCchCopy(buffer, ARRAYSIZE(buffer), L"<unknown>");
SetWindowText(controlWindow, buffer);
}
controlWindow = GetDlgItem(hwnd, IDC_EDIT_CONNECTION);
if (NULL != controlWindow)
{
buffer[0] = L'\0';
if (NULL != self->device)
{
const char *connectionName;
ifc_deviceconnection *connection;
connectionName = self->device->GetConnection();
if (NULL != WASABI_API_DEVICES &&
S_OK == WASABI_API_DEVICES->ConnectionFind(connectionName, &connection))
{
if (FAILED(connection->GetDisplayName(buffer, ARRAYSIZE(buffer))))
buffer[0] = L'\0';
connection->Release();
}
if (L'\0' == *buffer)
MultiByteToWideChar(CP_UTF8, 0, connectionName, -1, buffer, ARRAYSIZE(buffer));
}
if (L'\0' == *buffer)
StringCchCopy(buffer, ARRAYSIZE(buffer), L"<unknown>");
SetWindowText(controlWindow, buffer);
}
controlWindow = GetDlgItem(hwnd, IDC_COMBO_ATTACHED);
if (NULL != controlWindow)
{
SendMessage(controlWindow, CB_RESETCONTENT, 0, 0L);
if (NULL != self->device)
{
const wchar_t *searchString;
SendMessage(controlWindow, CB_ADDSTRING, 0, (LPARAM)L"Yes");
SendMessage(controlWindow, CB_ADDSTRING, 0, (LPARAM)L"No");
if (FALSE == self->device->GetAttached())
searchString = L"No";
else
searchString = L"Yes";
SendMessage(controlWindow, CB_SELECTSTRING, -1, (LPARAM)searchString);
}
else
{
SendMessage(controlWindow, CB_ADDSTRING, 0, (LPARAM)L"<unknown>");
SendMessage(controlWindow, CB_SETCURSEL, 0, 0L);
}
}
controlWindow = GetDlgItem(hwnd, IDC_COMBO_VISIBLE);
if (NULL != controlWindow)
{
SendMessage(controlWindow, CB_RESETCONTENT, 0, 0L);
if (NULL != self->device)
{
const wchar_t *searchString;
SendMessage(controlWindow, CB_ADDSTRING, 0, (LPARAM)L"Yes");
SendMessage(controlWindow, CB_ADDSTRING, 0, (LPARAM)L"No");
if (FALSE != self->device->GetHidden())
searchString = L"No";
else
searchString = L"Yes";
SendMessage(controlWindow, CB_SELECTSTRING, -1, (LPARAM)searchString);
}
else
{
SendMessage(controlWindow, CB_ADDSTRING, 0, (LPARAM)L"<unknown>");
SendMessage(controlWindow, CB_SETCURSEL, 0, 0L);
}
}
DeviceView_InitCapacity(hwnd);
DeviceView_InitIcons(hwnd, NULL);
}
static INT_PTR
DeviceView_OnInitDialog(HWND hwnd, HWND focusWindow, LPARAM param)
{
DeviceView *self;
self = (DeviceView*)malloc(sizeof(DeviceView));
if (NULL != self)
{
ZeroMemory(self, sizeof(DeviceView));
if (FALSE == SetProp(hwnd, MAKEINTATOM(DEVICEVIEW_ATOM), self))
{
free(self);
self = NULL;
}
}
if (NULL == self)
{
DestroyWindow(hwnd);
return 0;
}
self->device = (Device*)param;
if (NULL != self->device)
self->device->AddRef();
DeviceView_InitView(hwnd);
SetWindowPos(hwnd, NULL, 0, 0, 0, 0,
SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE | SWP_FRAMECHANGED);
return 0;
}
static void
DeviceView_OnDestroy(HWND hwnd)
{
DeviceView *self;
DeviceView_DestroyIcons(hwnd);
self = DEVICEVIEW(hwnd);
RemoveProp(hwnd, MAKEINTATOM(DEVICEVIEW_ATOM));
if (NULL == self)
return;
if (NULL != self->device)
self->device->Release();
free(self);
}
static void
DeviceView_OnTitleEditChanged(HWND hwnd)
{
DeviceView *self;
HWND controlWindow;
wchar_t buffer[1024];
DEVICEVIEW_RET_VOID(self, hwnd);
controlWindow = GetDlgItem(hwnd, IDC_EDIT_TITLE);
if (NULL == controlWindow)
return;
if (NULL == self->device)
return;
GetWindowText(controlWindow, buffer, ARRAYSIZE(buffer));
self->device->SetDisplayName(buffer);
}
static void
DeviceView_OnAttachedComboChanged(HWND hwnd)
{
DeviceView *self;
HWND controlWindow;
wchar_t buffer[1024];
int index;
DEVICEVIEW_RET_VOID(self, hwnd);
controlWindow = GetDlgItem(hwnd, IDC_COMBO_ATTACHED);
if (NULL == controlWindow)
return;
if (NULL == self->device)
return;
index = (int)SendMessage(controlWindow, CB_GETCURSEL, 0, 0);
if (CB_ERR != index &&
CB_ERR != SendMessage(controlWindow, CB_GETLBTEXT, index, (LPARAM)buffer))
{
if (CSTR_EQUAL == CompareString(CSTR_INVARIANT, NORM_IGNORECASE, buffer, -1, L"Yes", -1))
{
self->device->Attach(NULL);
}
else if (CSTR_EQUAL == CompareString(CSTR_INVARIANT, NORM_IGNORECASE, buffer, -1, L"No", -1))
{
self->device->Detach(NULL);
}
}
}
static void
DeviceView_OnVisibleComboChanged(HWND hwnd)
{
DeviceView *self;
HWND controlWindow;
wchar_t buffer[1024];
int index;
DEVICEVIEW_RET_VOID(self, hwnd);
controlWindow = GetDlgItem(hwnd, IDC_COMBO_VISIBLE);
if (NULL == controlWindow)
return;
if (NULL == self->device)
return;
index = (int)SendMessage(controlWindow, CB_GETCURSEL, 0, 0);
if (-1 != index &&
CB_ERR != SendMessage(controlWindow, CB_GETLBTEXT, index, (LPARAM)buffer))
{
if (CSTR_EQUAL == CompareString(CSTR_INVARIANT, NORM_IGNORECASE, buffer, -1, L"Yes", -1))
{
self->device->SetHidden(FALSE);
}
else if (CSTR_EQUAL == CompareString(CSTR_INVARIANT, NORM_IGNORECASE, buffer, -1, L"No", -1))
{
self->device->SetHidden(TRUE);
}
}
}
static void
DeviceView_OnIconsComboChanged(HWND hwnd)
{
DeviceView *self;
HWND controlWindow, pictureWindow;
int index;
HBITMAP bitmap, previousBitmap;
DEVICEVIEW_RET_VOID(self, hwnd);
controlWindow = GetDlgItem(hwnd, IDC_COMBO_ICONS);
if (NULL == controlWindow)
return;
if (NULL == self->device)
return;
pictureWindow = GetDlgItem(hwnd, IDC_STATIC_PREVIEWICON);
if (NULL == pictureWindow)
return;
bitmap = NULL;
index = (int)SendMessage(controlWindow, CB_GETCURSEL, 0, 0);\
if (CB_ERR != index)
{
DeviceIconInfo *info;
info = (DeviceIconInfo*)SendMessage(controlWindow, CB_GETITEMDATA, index, 0L);
if (CB_ERR != (INT_PTR)info && NULL != info->path)
{
bitmap = DeviceView_LoadIcon(info->path);
}
}
previousBitmap = (HBITMAP)SendMessage(pictureWindow, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)bitmap);
if (NULL != previousBitmap)
DeleteObject(previousBitmap);
previousBitmap = (HBITMAP)SendMessage(pictureWindow, STM_GETIMAGE, IMAGE_BITMAP, 0L);
if(previousBitmap != bitmap)
{
if (NULL != bitmap)
DeleteObject(bitmap);
}
}
static void
DeviceView_OnTotalSpaceEditChanged(HWND hwnd)
{
DeviceView *self;
HWND controlWindow;
uint64_t totalSpace;
BOOL error;
DEVICEVIEW_RET_VOID(self, hwnd);
controlWindow = GetDlgItem(hwnd, IDC_SPIN_TOTALSPACE);
if (NULL == controlWindow)
return;
if (NULL == self->device)
return;
totalSpace = (size_t)SendMessage(controlWindow, UDM_GETPOS32, 0, (LPARAM)&error);
if (FALSE != error)
return;
if (FAILED(self->device->SetTotalSpace(totalSpace)))
{
if (FAILED(self->device->GetTotalSpace(&totalSpace)))
totalSpace = 0;
}
controlWindow = GetDlgItem(hwnd, IDC_SPIN_USEDSPACE);
if (NULL != controlWindow)
{
SendMessage(controlWindow, UDM_SETRANGE32, (WPARAM)0, (LPARAM)totalSpace);
}
}
static void
DeviceView_OnUsedSpaceEditChanged(HWND hwnd)
{
DeviceView *self;
HWND controlWindow;
uint64_t usedSpace;
BOOL error;
DEVICEVIEW_RET_VOID(self, hwnd);
controlWindow = GetDlgItem(hwnd, IDC_SPIN_USEDSPACE);
if (NULL == controlWindow)
return;
if (NULL == self->device)
return;
usedSpace = (size_t)SendMessage(controlWindow, UDM_GETPOS32, 0, (LPARAM)&error);
if (FALSE != error)
return;
if (FAILED(self->device->SetUsedSpace(usedSpace)))
{
if (FAILED(self->device->GetTotalSpace(&usedSpace)))
usedSpace = 0;
}
}
static void
DeviceView_OnCommand(HWND hwnd, INT commandId, INT eventId, HWND controlWindow)
{
switch(commandId)
{
case IDC_EDIT_TITLE:
switch(eventId)
{
case EN_CHANGE:
DeviceView_OnTitleEditChanged(hwnd);
break;
}
break;
case IDC_COMBO_ATTACHED:
switch(eventId)
{
case CBN_SELENDOK:
DeviceView_OnAttachedComboChanged(hwnd);
break;
}
break;
case IDC_COMBO_VISIBLE:
switch(eventId)
{
case CBN_SELENDOK:
DeviceView_OnVisibleComboChanged(hwnd);
break;
}
break;
case IDC_COMBO_ICONS:
switch(eventId)
{
case CBN_SELENDOK:
DeviceView_OnIconsComboChanged(hwnd);
break;
}
break;
case IDC_EDIT_TOTALSPACE:
switch(eventId)
{
case EN_CHANGE:
DeviceView_OnTotalSpaceEditChanged(hwnd);
break;
}
break;
case IDC_EDIT_USEDSPACE:
switch(eventId)
{
case EN_CHANGE:
DeviceView_OnUsedSpaceEditChanged(hwnd);
break;
}
break;
case IDC_BUTTON_NEWICON:
switch(eventId)
{
case BN_CLICKED:
DeviceView_NewIcon(hwnd);
break;
}
break;
case IDC_BUTTON_REMOVEICON:
switch(eventId)
{
case BN_CLICKED:
DeviceView_RemoveIcon(hwnd);
break;
}
break;
case IDC_BUTTON_EDITICON:
switch(eventId)
{
case BN_CLICKED:
DeviceView_EditIcon(hwnd);
break;
}
break;
}
}
static INT_PTR
DeviceView_DialogProc(HWND hwnd, unsigned int uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_INITDIALOG: return DeviceView_OnInitDialog(hwnd, (HWND)wParam, lParam);
case WM_DESTROY: DeviceView_OnDestroy(hwnd); return TRUE;
case WM_COMMAND: DeviceView_OnCommand(hwnd, LOWORD(wParam), HIWORD(wParam), (HWND)lParam); return TRUE;
}
return 0;
}
@@ -0,0 +1,15 @@
#ifndef _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_VIEW_HEADER
#define _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_VIEW_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
HWND
DeviceView_CreateWindow(HWND parentWindow,
Device *device);
#endif //_NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_VIEW_HEADER
@@ -0,0 +1,415 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="gen_deviceprovider"
ProjectGUID="{A3C7D830-CD01-4C2B-9E1A-FB62B5236BA9}"
RootNamespace="gen_deviceprovider"
Keyword="Win32Proj"
TargetFrameworkVersion="196613"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../..;../../wasabi;../../agave"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;GEN_DEVICEPROVIDER_EXPORTS"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
PrecompiledHeaderThrough=""
WarningLevel="3"
DebugInformationFormat="4"
EnablePREfast="false"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="comctl32.lib shlwapi.lib windowscodecs.lib"
OutputFile="$(ProgramFiles)\winamp\plugins\gen_deviceprovider.dll"
LinkIncremental="2"
IgnoreDefaultLibraryNames="msvcprt.lib"
GenerateDebugInformation="true"
ProgramDatabaseFile="$(OutDir)\$(TargetName).pdb"
SubSystem="2"
SupportUnloadOfDelayLoadedDLL="true"
ImportLibrary="$(OutDir)\$(TargetName).lib"
TargetMachine="1"
Profile="false"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
OutputDocumentFile="$(OutDir)\$(TargetName).xml"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="../..;../../wasabi;../../agave"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;GEN_DEVICEPROVIDER_EXPORTS"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="2"
PrecompiledHeaderThrough="main.h"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="comctl32.lib shlwapi.lib windowscodecs.lib"
OutputFile="$(ProgramFiles)\winamp\plugins\gen_deviceprovider.dll"
LinkIncremental="1"
IgnoreDefaultLibraryNames="msvcprt.lib"
GenerateDebugInformation="true"
ProgramDatabaseFile="$(OutDir)\$(TargetName).pdb"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
SupportUnloadOfDelayLoadedDLL="true"
ImportLibrary="$(OutDir)\$(TargetName).lib"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
OutputDocumentFile="$(OutDir)\$(TargetName).xml"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="nu"
>
<File
RelativePath="..\..\nu\PtrList.cpp"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\nu\PtrList.h"
>
</File>
<File
RelativePath="..\..\nu\trace.cpp"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\nu\trace.h"
>
</File>
</Filter>
<File
RelativePath=".\common.h"
>
</File>
<File
RelativePath=".\device.cpp"
>
</File>
<File
RelativePath=".\device.h"
>
</File>
<File
RelativePath=".\deviceActivity.cpp"
>
</File>
<File
RelativePath=".\deviceActivity.h"
>
</File>
<File
RelativePath=".\deviceCommandNodeParser.cpp"
>
</File>
<File
RelativePath=".\deviceCommandNodeParser.h"
>
</File>
<File
RelativePath=".\deviceCommandParser.cpp"
>
</File>
<File
RelativePath=".\deviceCommandParser.h"
>
</File>
<File
RelativePath=".\deviceConnectionNodeParser.cpp"
>
</File>
<File
RelativePath=".\deviceConnectionNodeParser.h"
>
</File>
<File
RelativePath=".\deviceConnectionParser.cpp"
>
</File>
<File
RelativePath=".\deviceConnectionParser.h"
>
</File>
<File
RelativePath=".\deviceIconEditor.cpp"
>
</File>
<File
RelativePath=".\deviceIconEditor.h"
>
</File>
<File
RelativePath=".\deviceNodeParser.cpp"
>
</File>
<File
RelativePath=".\deviceNodeParser.h"
>
</File>
<File
RelativePath=".\deviceParser.cpp"
>
</File>
<File
RelativePath=".\deviceParser.h"
>
</File>
<File
RelativePath=".\deviceTypeNodeParser.cpp"
>
</File>
<File
RelativePath=".\deviceTypeNodeParser.h"
>
</File>
<File
RelativePath=".\deviceTypeParser.cpp"
>
</File>
<File
RelativePath=".\deviceTypeParser.h"
>
</File>
<File
RelativePath=".\deviceView.cpp"
>
</File>
<File
RelativePath=".\deviceView.h"
>
</File>
<File
RelativePath=".\iconStore.cpp"
>
</File>
<File
RelativePath=".\iconStore.h"
>
</File>
<File
RelativePath=".\main.cpp"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
</File>
<File
RelativePath=".\main.h"
>
</File>
<File
RelativePath=".\plugin.cpp"
>
</File>
<File
RelativePath=".\plugin.h"
>
</File>
<File
RelativePath=".\provider.cpp"
>
</File>
<File
RelativePath=".\provider.h"
>
</File>
<File
RelativePath=".\resource.h"
>
</File>
<File
RelativePath=".\resources.rc"
>
</File>
<File
RelativePath=".\stringBuilder.cpp"
>
</File>
<File
RelativePath=".\stringBuilder.h"
>
</File>
<File
RelativePath=".\strings.cpp"
>
</File>
<File
RelativePath=".\strings.h"
>
</File>
<File
RelativePath=".\testSuite.cpp"
>
</File>
<File
RelativePath=".\testSuite.h"
>
</File>
<File
RelativePath=".\testSuiteLoader.cpp"
>
</File>
<File
RelativePath=".\testSuiteLoader.h"
>
</File>
<File
RelativePath=".\wasabi.cpp"
>
</File>
<File
RelativePath=".\wasabi.h"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
@@ -0,0 +1,335 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{A3C7D830-CD01-4C2B-9E1A-FB62B5236BA9}</ProjectGuid>
<RootNamespace>gen_deviceprovider</RootNamespace>
<WindowsTargetPlatformVersion>10.0.19041.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
<IncludePath>$(IncludePath)</IncludePath>
<LibraryPath>$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
<IncludePath>$(IncludePath)</IncludePath>
<LibraryPath>$(LibraryPath)</LibraryPath>
<EmbedManifest>true</EmbedManifest>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Label="Vcpkg">
<VcpkgEnableManifest>false</VcpkgEnableManifest>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<VcpkgInstalledDir>
</VcpkgInstalledDir>
<VcpkgUseStatic>false</VcpkgUseStatic>
<VcpkgConfiguration>Debug</VcpkgConfiguration>
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<VcpkgInstalledDir>
</VcpkgInstalledDir>
<VcpkgUseStatic>false</VcpkgUseStatic>
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<VcpkgInstalledDir>
</VcpkgInstalledDir>
<VcpkgUseStatic>false</VcpkgUseStatic>
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
<VcpkgConfiguration>Debug</VcpkgConfiguration>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<VcpkgInstalledDir>
</VcpkgInstalledDir>
<VcpkgUseStatic>false</VcpkgUseStatic>
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>../..;..\..\..\;..\..\..\..\wasabi;..\..\..\..\agave;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;WIN32;_DEBUG;_WINDOWS;_USRDLL;GEN_DEVICEPROVIDER_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<EnablePREfast>false</EnablePREfast>
<BufferSecurityCheck>true</BufferSecurityCheck>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<FunctionLevelLinking>true</FunctionLevelLinking>
</ClCompile>
<Link>
<AdditionalDependencies>comctl32.lib;shlwapi.lib;windowscodecs.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
<SubSystem>Windows</SubSystem>
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
<TargetMachine>MachineX86</TargetMachine>
<Profile>false</Profile>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
<Xdcmake>
<OutputFile>$(IntDir)$(TargetName).xml</OutputFile>
</Xdcmake>
<PostBuildEvent>
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\
xcopy /Y /D $(IntDir)$(TargetName).pdb ..\..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\ </Command>
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\'</Message>
</PostBuildEvent>
<ResourceCompile>
<PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>../..;..\..\..\..\;..\..\..\..\wasabi;..\..\..\..\agave;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;WIN64;_DEBUG;_WINDOWS;_USRDLL;GEN_DEVICEPROVIDER_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<EnablePREfast>false</EnablePREfast>
<BufferSecurityCheck>true</BufferSecurityCheck>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<FunctionLevelLinking>true</FunctionLevelLinking>
</ClCompile>
<Link>
<AdditionalDependencies>comctl32.lib;shlwapi.lib;windowscodecs.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
<SubSystem>Windows</SubSystem>
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
<Profile>false</Profile>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
<Xdcmake>
<OutputFile>$(IntDir)$(TargetName).xml</OutputFile>
</Xdcmake>
<PostBuildEvent>
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\
xcopy /Y /D $(IntDir)$(TargetName).pdb ..\..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\ </Command>
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\'</Message>
</PostBuildEvent>
<ResourceCompile>
<PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>../..;..\..\..\..\;..\..\..\..\wasabi;..\..\..\..\agave;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;WIN32;NDEBUG;_WINDOWS;_USRDLL;GEN_DEVICEPROVIDER_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>None</DebugInformationFormat>
<StringPooling>true</StringPooling>
<BufferSecurityCheck>true</BufferSecurityCheck>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
</ClCompile>
<Link>
<AdditionalDependencies>comctl32.lib;shlwapi.lib;windowscodecs.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<GenerateDebugInformation>false</GenerateDebugInformation>
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
<SubSystem>Windows</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
<TargetMachine>MachineX86</TargetMachine>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
<Xdcmake>
<OutputFile>$(IntDir)$(TargetName).xml</OutputFile>
</Xdcmake>
<PostBuildEvent>
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\ </Command>
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\'</Message>
</PostBuildEvent>
<ResourceCompile>
<PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>../..;..\..\..\..\;..\..\..\..\wasabi;..\..\..\..\agave;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;WIN64;NDEBUG;_WINDOWS;_USRDLL;GEN_DEVICEPROVIDER_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>None</DebugInformationFormat>
<StringPooling>true</StringPooling>
<BufferSecurityCheck>true</BufferSecurityCheck>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
</ClCompile>
<Link>
<AdditionalDependencies>comctl32.lib;shlwapi.lib;windowscodecs.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<GenerateDebugInformation>false</GenerateDebugInformation>
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
<SubSystem>Windows</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
<Xdcmake>
<OutputFile>$(IntDir)$(TargetName).xml</OutputFile>
</Xdcmake>
<PostBuildEvent>
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\ </Command>
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\'</Message>
</PostBuildEvent>
<ResourceCompile>
<PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\..\..\nu\PtrList.cpp" />
<ClCompile Include="..\..\..\..\nu\trace.cpp" />
<ClCompile Include="device.cpp" />
<ClCompile Include="deviceActivity.cpp" />
<ClCompile Include="deviceCommandNodeParser.cpp" />
<ClCompile Include="deviceCommandParser.cpp" />
<ClCompile Include="deviceConnectionNodeParser.cpp" />
<ClCompile Include="deviceConnectionParser.cpp" />
<ClCompile Include="deviceIconEditor.cpp" />
<ClCompile Include="deviceNodeParser.cpp" />
<ClCompile Include="deviceParser.cpp" />
<ClCompile Include="deviceTypeNodeParser.cpp" />
<ClCompile Include="deviceTypeParser.cpp" />
<ClCompile Include="deviceView.cpp" />
<ClCompile Include="iconStore.cpp" />
<ClCompile Include="main.cpp" />
<ClCompile Include="plugin.cpp" />
<ClCompile Include="provider.cpp" />
<ClCompile Include="stringBuilder.cpp" />
<ClCompile Include="strings.cpp" />
<ClCompile Include="testSuite.cpp" />
<ClCompile Include="testSuiteLoader.cpp" />
<ClCompile Include="wasabi.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\..\nu\trace.h" />
<ClInclude Include="common.h" />
<ClInclude Include="device.h" />
<ClInclude Include="deviceActivity.h" />
<ClInclude Include="deviceCommandNodeParser.h" />
<ClInclude Include="deviceCommandParser.h" />
<ClInclude Include="deviceConnectionNodeParser.h" />
<ClInclude Include="deviceConnectionParser.h" />
<ClInclude Include="deviceIconEditor.h" />
<ClInclude Include="deviceNodeParser.h" />
<ClInclude Include="deviceParser.h" />
<ClInclude Include="deviceTypeNodeParser.h" />
<ClInclude Include="deviceTypeParser.h" />
<ClInclude Include="deviceView.h" />
<ClInclude Include="iconStore.h" />
<ClInclude Include="main.h" />
<ClInclude Include="plugin.h" />
<ClInclude Include="provider.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="stringBuilder.h" />
<ClInclude Include="strings.h" />
<ClInclude Include="testSuite.h" />
<ClInclude Include="testSuiteLoader.h" />
<ClInclude Include="wasabi.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="resources.rc" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\Wasabi\Wasabi.vcxproj">
<Project>{3e0bfa8a-b86a-42e9-a33f-ec294f823f7f}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
@@ -0,0 +1,164 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="device.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="deviceActivity.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="deviceCommandNodeParser.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="deviceCommandParser.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="deviceConnectionNodeParser.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="deviceConnectionParser.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="deviceIconEditor.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="deviceNodeParser.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="deviceParser.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="deviceTypeNodeParser.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="deviceTypeParser.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="deviceView.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="iconStore.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="plugin.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="provider.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="stringBuilder.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="strings.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="testSuite.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="testSuiteLoader.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="wasabi.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\..\..\nu\trace.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\..\..\nu\PtrList.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="common.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="device.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="deviceActivity.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="deviceCommandNodeParser.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="deviceCommandParser.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="deviceConnectionNodeParser.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="deviceConnectionParser.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="deviceIconEditor.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="deviceNodeParser.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="deviceParser.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="deviceTypeNodeParser.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="deviceTypeParser.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="deviceView.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="iconStore.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="main.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="plugin.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="provider.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="resource.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="stringBuilder.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="strings.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="testSuite.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="testSuiteLoader.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="wasabi.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\nu\trace.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="Header Files">
<UniqueIdentifier>{e264ea99-159e-4062-a78a-a85da3815f37}</UniqueIdentifier>
</Filter>
<Filter Include="Ressource Files">
<UniqueIdentifier>{f5beaf0a-f21d-4ae9-8221-adde13e2b65d}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files">
<UniqueIdentifier>{207087f5-3450-4826-bae5-39064e9da43f}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="resources.rc">
<Filter>Ressource Files</Filter>
</ResourceCompile>
</ItemGroup>
</Project>
@@ -0,0 +1,289 @@
#include "main.h"
#include "./iconStore.h"
#include <vector>
typedef struct IconStoreRecord
{
unsigned int width;
unsigned int height;
wchar_t *path;
} IconStoreRecord;
typedef std::vector<IconStoreRecord> RecodList;
struct IconStore
{
RecodList list;
wchar_t *basePath;
};
IconStore *
IconStore_Create()
{
IconStore *self;
self = new IconStore();
if (NULL == self)
return NULL;
self->basePath = NULL;
return self;
}
void
IconStore_Destroy(IconStore *self)
{
size_t index;
IconStoreRecord *record;
if (NULL == self)
return;
index = self->list.size();
while(index--)
{
record = &self->list[index];
String_Free(record->path);
}
String_Free(self->basePath);
}
BOOL
IconStore_Add(IconStore *self, const wchar_t *path, unsigned int width, unsigned int height)
{
IconStoreRecord record, *prec;
size_t index;
if (NULL == self)
return FALSE;
if(width < 1)
width = 1;
if(height < 1)
height = 1;
index = self->list.size();
while(index--)
{
prec = &self->list[index];
if (width == prec->width &&
height == prec->height)
{
String_Free(prec->path);
prec->path = String_Duplicate(path);
return TRUE;
}
}
record.path = String_Duplicate(path);
record.width = width;
record.height = height;
self->list.push_back(record);
return TRUE;
}
BOOL
IconStore_RemovePath(IconStore *self, const wchar_t *path)
{
size_t index;
IconStoreRecord *record;
if (NULL == self)
return FALSE;
index = self->list.size();
while(index--)
{
record = &self->list[index];
if(CSTR_EQUAL == CompareString(CSTR_INVARIANT, NORM_IGNORECASE, record->path, -1, path, -1))
{
self->list.eraseAt(index);
}
}
return TRUE;
}
BOOL
IconStore_Remove(IconStore *self, unsigned int width, unsigned int height)
{
size_t index;
IconStoreRecord *record;
if (NULL == self)
return FALSE;
index = self->list.size();
while(index--)
{
record = &self->list[index];
if(record->width == width &&
record->height == height)
{
self->list.eraseAt(index);
}
}
return TRUE;
}
static BOOL
IconStore_GetFullPath(IconStore *self, const wchar_t *path, wchar_t *buffer, size_t bufferMax)
{
if (NULL == buffer)
return FALSE;
if (NULL == self)
return FALSE;
if (FALSE != IS_STRING_EMPTY(path))
{
*buffer = L'\0';
return TRUE;
}
if (FALSE == PathIsRelative(path) ||
IS_STRING_EMPTY(self->basePath))
{
if (0 == String_CopyTo(buffer, path, bufferMax) &&
FALSE == IS_STRING_EMPTY(path))
return FALSE;
else
return TRUE;
}
if (NULL == PathCombine(buffer, self->basePath, path))
return FALSE;
return TRUE;
}
BOOL
IconStore_Get(IconStore *self, wchar_t *buffer, size_t bufferMax, unsigned int width, unsigned int height)
{
const wchar_t *icon;
IconStoreRecord *record;
size_t index;
double widthDbl, heightDbl;
double scaleMin, scaleHorz, scaleVert;
if (NULL == self)
return FALSE;
if (NULL == buffer)
return FALSE;
icon = NULL;
widthDbl = width;
heightDbl = height;
index = self->list.size();
if (index > 0)
{
record = &self->list[--index];
scaleHorz = widthDbl/record->width;
scaleVert = heightDbl/record->height;
scaleMin = (scaleHorz < scaleVert) ? scaleHorz : scaleVert;
icon = record->path;
if (1.0 != scaleMin)
{
scaleMin = fabs(1.0 - scaleMin);
while(index--)
{
record = &self->list[index];
scaleHorz = widthDbl/record->width;
scaleVert = heightDbl/record->height;
if (scaleHorz > scaleVert)
scaleHorz = scaleVert;
if (1.0 == scaleHorz)
{
icon = record->path;
break;
}
scaleHorz = fabs(1.0 - scaleHorz);
if (scaleHorz < scaleMin)
{
scaleMin = scaleHorz;
icon = record->path;
}
}
}
}
return IconStore_GetFullPath(self, icon, buffer, bufferMax);
}
BOOL
IconStore_SetBasePath(IconStore *self, const wchar_t *path)
{
if (NULL == self)
return FALSE;
String_Free(self->basePath);
self->basePath = String_Duplicate(path);
return TRUE;
}
IconStore *
IconStore_Clone(IconStore *self)
{
size_t index;
IconStore *clone;
IconStoreRecord targetRec;
const IconStoreRecord *sourceRec;
if (NULL == self)
return NULL;
clone = IconStore_Create();
if (NULL == clone)
return NULL;
clone->basePath = String_Duplicate(self->basePath);
for(index = 0; index < self->list.size(); index++)
{
sourceRec = &self->list[index];
targetRec.path = String_Duplicate(sourceRec->path);
targetRec.width = sourceRec->width;
targetRec.height = sourceRec->height;
clone->list.push_back(targetRec);
}
return clone;
}
BOOL
IconStore_Enumerate(IconStore *self, IconEnumerator callback, void *user)
{
size_t index;
wchar_t buffer[MAX_PATH*2];
IconStoreRecord *record;
if (NULL == self || NULL == callback)
return FALSE;
index = self->list.size();
while(index--)
{
record = &self->list[index];
if (FALSE != IconStore_GetFullPath(self, record->path, buffer, ARRAYSIZE(buffer)))
{
if (FALSE == callback(buffer, record->width, record->height, user))
return TRUE;
}
}
return TRUE;
}
@@ -0,0 +1,53 @@
#ifndef _NULLSOFT_WINAMP_GEN_DEVICE_ICON_STORE_HEADER
#define _NULLSOFT_WINAMP_GEN_DEVICE_ICON_STORE_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
typedef struct IconStore IconStore;
typedef BOOL (*IconEnumerator)(const wchar_t *path, unsigned int width, unsigned int height, void *user);
IconStore *
IconStore_Create();
void
IconStore_Destroy(IconStore *self);
BOOL
IconStore_Add(IconStore *self,
const wchar_t *path,
unsigned int width,
unsigned int height);
BOOL
IconStore_RemovePath(IconStore *self,
const wchar_t *path);
BOOL
IconStore_Remove(IconStore *self,
unsigned int width,
unsigned int height);
BOOL
IconStore_Get(IconStore *self,
wchar_t *buffer,
size_t bufferMax,
unsigned int width,
unsigned int height);
BOOL
IconStore_SetBasePath(IconStore *self,
const wchar_t *path);
IconStore *
IconStore_Clone(IconStore *self);
BOOL
IconStore_Enumerate(IconStore *self,
IconEnumerator callback,
void *user);
#endif //_NULLSOFT_WINAMP_GEN_DEVICE_ICON_STORE_HEADER
@@ -0,0 +1,2 @@
#include <initguid.h>
#include "main.h"
@@ -0,0 +1,31 @@
#ifndef _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_MAIN_HEADER
#define _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_MAIN_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
#include "./common.h"
#include "./plugin.h"
#include "./strings.h"
#include "./stringBuilder.h"
#include "./wasabi.h"
#include "./provider.h"
#include "./resource.h"
#include "./device.h"
#include "./deviceActivity.h"
#include "./deviceView.h"
#include "./deviceIconEditor.h"
#include "./testSuite.h"
#include "./testSuiteLoader.h"
#include "./iconStore.h"
#include "../../winamp/wa_ipc.h"
#include "../../nu/trace.h"
#include <math.h>
#include <shlwapi.h>
#endif //_NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_MAIN_HEADER
@@ -0,0 +1,114 @@
#include "main.h"
#include "../../winamp/gen.h"
#include <strsafe.h>
static INT
Plugin_Init(void);
static void
Plugin_Quit(void);
static void
Plugin_Config(void);
extern "C" winampGeneralPurposePlugin plugin =
{
GPPHDR_VER,
0,
Plugin_Init,
Plugin_Config,
Plugin_Quit,
};
static DeviceProvider *deviceProvider = NULL;
HINSTANCE
Plugin_GetInstance(void)
{
return plugin.hDllInstance;
}
HWND
Plugin_GetWinampWindow(void)
{
return plugin.hwndParent;
}
static void
Plugin_SetDescription()
{
WCHAR szBuffer[256], szTemplate[256];
if (0 != plugin.description)
AnsiString_Free(plugin.description);
if (NULL != WASABI_API_LNG)
WASABI_API_LNGSTRINGW_BUF(IDS_PLUGIN_NAME, szTemplate, ARRAYSIZE(szTemplate));
else
szTemplate[0] = L'\0';
StringCchPrintf(szBuffer, ARRAYSIZE(szBuffer),
((L'\0' != szTemplate[0]) ? szTemplate : L"Nullsoft Test Device Provider v%d.%d"),
PLUGIN_VERSION_MAJOR, PLUGIN_VERSION_MINOR);
plugin.description = String_ToAnsi(CP_ACP, 0, szBuffer, -1, NULL, NULL);
}
static INT
Plugin_Init(void)
{
if (FALSE == Wasabi_InitializeFromWinamp(plugin.hDllInstance, plugin.hwndParent))
return 1;
Wasabi_LoadDefaultServices();
Plugin_SetDescription();
if (NULL == deviceProvider)
{
if (FAILED(DeviceProvider::CreateInstance(&deviceProvider)))
{
Wasabi_Release();
return 2;
}
deviceProvider->Register(WASABI_API_DEVICES);
}
return 0;
}
static void
Plugin_Quit(void)
{
if (0 != plugin.description)
{
AnsiString_Free(plugin.description);
plugin.description = 0;
}
if (NULL != deviceProvider)
{
deviceProvider->Unregister(WASABI_API_DEVICES);
deviceProvider->Release();
}
Wasabi_Release();
}
static void
Plugin_Config(void)
{
}
EXTERN_C __declspec(dllexport) winampGeneralPurposePlugin *
winampGetGeneralPurposePlugin()
{
if (0 == plugin.description)
{
Plugin_SetDescription();
}
return &plugin;
}
@@ -0,0 +1,21 @@
#ifndef _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_PLUGIN_HEADER
#define _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_PLUGIN_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
#define PLUGIN_VERSION_MAJOR 1
#define PLUGIN_VERSION_MINOR 1
// {51B54A05-B711-4509-80AE-5A0AAA502FA5}
DEFINE_GUID(PLUGIN_LANGUAGE_ID,
0x51b54a05, 0xb711, 0x4509, 0x80, 0xae, 0x5a, 0xa, 0xaa, 0x50, 0x2f, 0xa5);
HINSTANCE Plugin_GetInstance(void);
HWND Plugin_GetWinampWindow(void);
#endif //_NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_PLUGIN_HEADER
@@ -0,0 +1,336 @@
#include "main.h"
#include "./provider.h"
typedef struct DeviceProviderThreadParam
{
api_devicemanager *manager;
DeviceProvider *provider;
HANDLE readyEvent;
}DeviceProviderThreadParam;
DeviceProvider::DeviceProvider()
: ref(1), discoveryThread(NULL), cancelEvent(NULL)
{
wchar_t buffer[MAX_PATH * 2];
HINSTANCE module;
TestSuiteLoader loader;
InitializeCriticalSection(&lock);
module = Plugin_GetInstance();
if (0 == GetModuleFileName(module, buffer, ARRAYSIZE(buffer)) ||
FALSE == PathRemoveFileSpec(buffer))
{
buffer[0] = L'\0';
}
PathAppend(buffer, L"testprovider.xml");
loader.Load(buffer, &testSuite);
}
DeviceProvider::~DeviceProvider()
{
CancelDiscovery();
DeleteCriticalSection(&lock);
}
HRESULT DeviceProvider::CreateInstance(DeviceProvider **instance)
{
if (NULL == instance)
return E_POINTER;
*instance = new DeviceProvider();
if (NULL == *instance)
return E_OUTOFMEMORY;
return S_OK;
}
size_t DeviceProvider::AddRef()
{
return InterlockedIncrement((LONG*)&ref);
}
size_t DeviceProvider::Release()
{
if (0 == ref)
return ref;
LONG r = InterlockedDecrement((LONG*)&ref);
if (0 == r)
delete(this);
return r;
}
int DeviceProvider::QueryInterface(GUID interface_guid, void **object)
{
if (NULL == object)
return E_POINTER;
if (IsEqualIID(interface_guid, IFC_DeviceProvider))
*object = static_cast<ifc_deviceprovider*>(this);
else
{
*object = NULL;
return E_NOINTERFACE;
}
if (NULL == *object)
return E_UNEXPECTED;
AddRef();
return S_OK;
}
DWORD DeviceProvider::DiscoveryThread(api_devicemanager *manager)
{
DWORD waitResult;
DWORD deviceCount;
DWORD threadId;
DWORD sleepTime;
LARGE_INTEGER perfCounter;
deviceCount = 0;
threadId = GetCurrentThreadId();
// aTRACE_FMT("[test provider] device discovery started (0x%X).\r\n", threadId);
manager->SetProviderActive(this, TRUE);
for(;;)
{
if (FALSE != QueryPerformanceCounter(&perfCounter))
srand(perfCounter.LowPart);
else
srand(GetTickCount());
sleepTime = (DWORD)((double)rand()/(RAND_MAX) * 0);
waitResult = WaitForSingleObject(cancelEvent, sleepTime);
if (WAIT_OBJECT_0 == waitResult)
break;
else if (WAIT_TIMEOUT == waitResult)
{
Device *device;
deviceCount++;
// aTRACE_FMT("[test provider] creating new device[%d] (0x%X).\r\n", deviceCount, threadId);
device = testSuite.GetRandomDevice();
if (NULL != device)
{
device->Connect();
if (0 == manager->DeviceRegister((ifc_device**)&device, 1))
device->Disconnect();
}
if (4 == deviceCount)
break;
}
else
{
// aTRACE_FMT("[test provider] error (0x%X).\r\n", threadId);
break;
}
}
EnterCriticalSection(&lock);
if (NULL != discoveryThread)
{
CloseHandle(discoveryThread);
discoveryThread = NULL;
}
if (NULL != cancelEvent)
{
CloseHandle(cancelEvent);
cancelEvent = NULL;
}
// aTRACE_FMT("[test provider] device discovery finished (0x%X).\r\n", threadId);
LeaveCriticalSection(&lock);
manager->SetProviderActive(this, FALSE);
return 0;
}
static DWORD CALLBACK DeviceProvider_DiscoveryThreadStarter(void *user)
{
DeviceProviderThreadParam *param;
DeviceProvider *provider;
api_devicemanager *manager;
DWORD result;
param = (DeviceProviderThreadParam*)user;
manager = param->manager;
provider = param->provider;
if (NULL != manager)
manager->AddRef();
if (NULL != param->readyEvent)
SetEvent(param->readyEvent);
if (NULL == manager)
return -1;
if (NULL != provider)
result = provider->DiscoveryThread(manager);
else
result = -2;
manager->Release();
return result;
}
HRESULT DeviceProvider::BeginDiscovery(api_devicemanager *manager)
{
HRESULT hr;
if (NULL == manager)
return E_INVALIDARG;
EnterCriticalSection(&lock);
if (NULL != discoveryThread)
hr = E_PENDING;
else
{
hr = S_OK;
if (NULL == cancelEvent)
{
cancelEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (NULL == cancelEvent)
hr = E_FAIL;
}
if (SUCCEEDED(hr))
{
DeviceProviderThreadParam param;
param.provider = this;
param.manager = manager;
param.readyEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (NULL == param.readyEvent)
hr = E_FAIL;
else
{
DWORD threadId;
discoveryThread = CreateThread(NULL, 0, DeviceProvider_DiscoveryThreadStarter, &param, 0, &threadId);
if (NULL == discoveryThread)
hr = E_FAIL;
else
WaitForSingleObject(param.readyEvent, INFINITE);
CloseHandle(param.readyEvent);
}
}
if (FAILED(hr))
CancelDiscovery();
}
LeaveCriticalSection(&lock);
return hr;
}
HRESULT DeviceProvider::CancelDiscovery()
{
HRESULT hr;
HANDLE threadHandle, eventHandle;
EnterCriticalSection(&lock);
threadHandle = discoveryThread;
eventHandle = cancelEvent;
discoveryThread = NULL;
cancelEvent = NULL;
LeaveCriticalSection(&lock);
if (NULL != threadHandle)
{
if (NULL != eventHandle)
SetEvent(eventHandle);
WaitForSingleObject(threadHandle, INFINITE);
CloseHandle(threadHandle);
hr = S_OK;
}
else
hr = S_FALSE;
if (NULL != eventHandle)
CloseHandle(eventHandle);
return hr;
}
HRESULT DeviceProvider::GetActive()
{
HRESULT hr;
EnterCriticalSection(&lock);
hr = (NULL != discoveryThread) ? S_OK : S_FALSE;
LeaveCriticalSection(&lock);
return hr;
}
HRESULT DeviceProvider::Register(api_devicemanager *manager)
{
HRESULT hr;
if (NULL == manager)
return E_POINTER;
hr = manager->RegisterProvider(this);
if (SUCCEEDED(hr))
{
testSuite.RegisterCommands(manager);
testSuite.RegisterTypes(manager);
testSuite.RegisterConnections(manager);
testSuite.RegisterDevices(manager);
}
return hr;
}
HRESULT DeviceProvider::Unregister(api_devicemanager *manager)
{
HRESULT hr;
if (NULL == manager)
return E_POINTER;
hr = manager->UnregisterProvider(this);
testSuite.UnregisterTypes(manager);
testSuite.UnregisterConnections(manager);
testSuite.UnregisterCommands(manager);
testSuite.UnregisterDevices(manager);
return hr;
}
#define CBCLASS DeviceProvider
START_DISPATCH;
CB(ADDREF, AddRef)
CB(RELEASE, Release)
CB(QUERYINTERFACE, QueryInterface)
CB(API_BEGINDISCOVERY, BeginDiscovery)
CB(API_CANCELDISCOVERY, CancelDiscovery)
CB(API_GETACTIVE, GetActive)
END_DISPATCH;
#undef CBCLASS
@@ -0,0 +1,50 @@
#ifndef _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_IMPLEMENTATION_HEADER
#define _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_IMPLEMENTATION_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
#include "../../devices/ifc_deviceprovider.h"
#include "./testSuite.h"
class DeviceProvider : public ifc_deviceprovider
{
protected:
DeviceProvider();
~DeviceProvider();
public:
static HRESULT CreateInstance(DeviceProvider **instance);
public:
/* Dispatchable */
size_t AddRef();
size_t Release();
int QueryInterface(GUID interface_guid, void **object);
/* ifc_deviceprovider */
HRESULT BeginDiscovery(api_devicemanager *manager);
HRESULT CancelDiscovery();
HRESULT GetActive();
public:
HRESULT Register(api_devicemanager *manager);
HRESULT Unregister(api_devicemanager *manager);
private:
DWORD DiscoveryThread(api_devicemanager *manager);
friend static DWORD CALLBACK DeviceProvider_DiscoveryThreadStarter(void *param);
protected:
size_t ref;
HANDLE discoveryThread;
HANDLE cancelEvent;
TestSuite testSuite;
CRITICAL_SECTION lock;
protected:
RECVS_DISPATCH;
};
#endif //_NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_IMPLEMENTATION_HEADER
@@ -0,0 +1,39 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by resources.rc
//
#define IDS_PLUGIN_NAME 101
#define IDD_DEVICE_VIEW 102
#define IDD_ICON_EDITOR 104
#define IDC_EDIT_NAME 1001
#define IDC_EDIT_TITLE 1002
#define IDC_EDIT_TYPE 1003
#define IDC_EDIT_CONNECTION 1004
#define IDC_COMBO_ATTACHED 1005
#define IDC_COMBO_VISIBLE 1006
#define IDC_EDIT_TOTALSPACE 1007
#define IDC_SPIN_TOTALSPACE 1008
#define IDC_EDIT_USEDSPACE 1009
#define IDC_SPIN_USEDSPACE 1010
#define IDC_COMBO_ICONS 1011
#define IDC_BUTTON_NEWICON 1012
#define IDC_BUTTON_REMOVEICON 1013
#define IDC_STATIC_PREVIEWICON 1014
#define IDC_EDIT_WIDTH 1015
#define IDC_EDIT_HEIGHT 1016
#define IDC_EDIT_PATH 1017
#define IDC_BUTTON_BROWSE 1018
#define IDC_BUTTON1 1019
#define IDC_BUTTON_EDITICON 1019
#define IDS_STRING102 65535
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 105
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1020
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
@@ -0,0 +1,186 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_DEVICE_VIEW DIALOGEX 0, 0, 397, 282
STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN
EXSTYLE WS_EX_NOPARENTNOTIFY | WS_EX_CONTROLPARENT
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
EDITTEXT IDC_EDIT_NAME,57,23,101,12,ES_AUTOHSCROLL | ES_READONLY
EDITTEXT IDC_EDIT_TYPE,57,36,101,12,ES_AUTOHSCROLL | ES_READONLY
EDITTEXT IDC_EDIT_CONNECTION,57,50,101,12,ES_AUTOHSCROLL | ES_READONLY
EDITTEXT IDC_EDIT_TITLE,57,70,101,12,ES_AUTOHSCROLL
COMBOBOX IDC_COMBO_ATTACHED,57,85,101,30,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
COMBOBOX IDC_COMBO_VISIBLE,57,101,101,30,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
EDITTEXT IDC_EDIT_TOTALSPACE,57,117,101,16,ES_AUTOHSCROLL | ES_NUMBER
CONTROL "",IDC_SPIN_TOTALSPACE,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,149,118,9,12,WS_EX_TRANSPARENT
EDITTEXT IDC_EDIT_USEDSPACE,57,134,101,16,ES_AUTOHSCROLL | ES_NUMBER
CONTROL "",IDC_SPIN_USEDSPACE,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,149,136,9,12,WS_EX_TRANSPARENT
COMBOBOX IDC_COMBO_ICONS,169,34,221,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
PUSHBUTTON "New",IDC_BUTTON_NEWICON,264,49,40,14
PUSHBUTTON "Edit",IDC_BUTTON_EDITICON,307,49,40,14
PUSHBUTTON "Remove",IDC_BUTTON_REMOVEICON,350,49,40,14
CONTROL "",IDC_STATIC_PREVIEWICON,"Static",SS_BITMAP | SS_CENTERIMAGE,169,70,221,170,WS_EX_STATICEDGE
LTEXT "Device View",IDC_STATIC,7,7,39,8
CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,7,16,383,1
LTEXT "Name:",IDC_STATIC,15,24,22,8
LTEXT "Title:",IDC_STATIC,15,71,17,8
LTEXT "Type:",IDC_STATIC,15,37,20,8
LTEXT "Connection:",IDC_STATIC,15,51,40,8
LTEXT "Attached:",IDC_STATIC,15,87,33,8
LTEXT "Visible:",IDC_STATIC,15,103,23,8
LTEXT "Capacity:",IDC_STATIC,15,119,32,8
LTEXT "Used Space:",IDC_STATIC,15,136,41,8
LTEXT "Icons:",IDC_STATIC,169,22,21,8
END
IDD_ICON_EDITOR DIALOGEX 0, 0, 290, 79
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Device Icon"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "OK",IDOK,180,58,50,14
PUSHBUTTON "Cancel",IDCANCEL,233,58,50,14
LTEXT "Width:",IDC_STATIC,8,34,35,8
LTEXT "Height:",IDC_STATIC,47,33,29,8
EDITTEXT IDC_EDIT_WIDTH,7,44,35,14,ES_AUTOHSCROLL | ES_NUMBER
EDITTEXT IDC_EDIT_HEIGHT,46,44,35,14,ES_AUTOHSCROLL | ES_NUMBER
EDITTEXT IDC_EDIT_PATH,7,18,250,14,ES_AUTOHSCROLL
LTEXT "Path:",IDC_STATIC,7,7,18,8
PUSHBUTTON "...",IDC_BUTTON_BROWSE,261,18,22,14
END
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
IDD_DEVICE_VIEW, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 390
VERTGUIDE, 15
VERTGUIDE, 57
VERTGUIDE, 158
VERTGUIDE, 169
TOPMARGIN, 7
BOTTOMMARGIN, 275
END
IDD_ICON_EDITOR, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 283
VERTGUIDE, 42
VERTGUIDE, 46
TOPMARGIN, 7
BOTTOMMARGIN, 72
END
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Dialog Info
//
IDD_DEVICE_VIEW DLGINIT
BEGIN
IDC_COMBO_ATTACHED, 0x403, 4, 0
0x6559, 0x0073,
IDC_COMBO_ATTACHED, 0x403, 3, 0
0x6f4e, "\000"
IDC_COMBO_VISIBLE, 0x403, 4, 0
0x6559, 0x0073,
IDC_COMBO_VISIBLE, 0x403, 3, 0
0x6f4e, "\000"
0
END
/////////////////////////////////////////////////////////////////////////////
//
// String Table
//
STRINGTABLE
BEGIN
IDS_PLUGIN_NAME "Nullsoft Test Device Provider v%d.%d"
END
STRINGTABLE
BEGIN
65535 "{51B54A05-B711-4509-80AE-5A0AAA502FA5}"
END
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED
@@ -0,0 +1,85 @@
#include "main.h"
#include "./stringBuilder.h"
#include <strsafe.h>
StringBuilder::StringBuilder()
: buffer(NULL), cursor(NULL), allocated(0), remaining(0)
{
}
StringBuilder::~StringBuilder()
{
String_Free(buffer);
}
HRESULT StringBuilder::Allocate(size_t newSize)
{
if (newSize <= allocated)
return S_FALSE;
LPWSTR t = String_ReAlloc(buffer, newSize);
if (NULL == t) return E_OUTOFMEMORY;
cursor = t + (cursor - buffer);
buffer = t;
remaining += newSize - allocated;
allocated = newSize;
return S_OK;
}
void StringBuilder::Clear(void)
{
if (NULL != buffer)
{
buffer[0] = L'\0';
}
cursor = buffer;
remaining = allocated;
}
LPCWSTR StringBuilder::Get(void)
{
return buffer;
}
HRESULT StringBuilder::Set(size_t index, WCHAR value)
{
if (NULL == buffer)
return E_POINTER;
if (index >= allocated)
return E_INVALIDARG;
buffer[index] = value;
return S_OK;
}
HRESULT StringBuilder::Append(LPCWSTR pszString)
{
HRESULT hr;
if (NULL == buffer)
{
hr = Allocate(1024);
if (FAILED(hr)) return hr;
}
size_t cchCursor = remaining;
hr = StringCchCopyEx(cursor, cchCursor, pszString, &cursor, &remaining, STRSAFE_IGNORE_NULLS);
if (STRSAFE_E_INSUFFICIENT_BUFFER == hr)
{
size_t offset = cchCursor - remaining;
size_t requested = lstrlen(pszString) + (allocated - remaining) + 1;
size_t newsize = allocated * 2;
while (newsize < requested) newsize = newsize * 2;
hr = Allocate(newsize);
if (FAILED(hr)) return hr;
hr = StringCchCopyEx(cursor, remaining, pszString + offset, &cursor, &remaining, STRSAFE_IGNORE_NULLS);
}
return hr;
}
@@ -0,0 +1,31 @@
#ifndef NULLSOFT_WINAMP_STRING_BUILDER_HEADER
#define NULLSOFT_WINAMP_STRING_BUILDER_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
class StringBuilder
{
public:
StringBuilder();
~StringBuilder();
public:
HRESULT Allocate(size_t newSize);
void Clear(void);
LPCWSTR Get(void);
HRESULT Set(size_t index, WCHAR value);
HRESULT Append(LPCWSTR pszString);
protected:
LPWSTR buffer;
LPWSTR cursor;
size_t allocated;
size_t remaining;
};
#endif //NULLSOFT_WINAMP_STRING_BUILDER_HEADER
@@ -0,0 +1,243 @@
#include "main.h"
#include "./strings.h"
#include <strsafe.h>
wchar_t *
String_Malloc(size_t size)
{
return (wchar_t *)malloc(sizeof(wchar_t) * size);
}
wchar_t *
String_ReAlloc(wchar_t *string, size_t size)
{
return (wchar_t *)realloc(string, sizeof(wchar_t) * size);
}
void
String_Free(wchar_t *string)
{
if (NULL != string)
free(string);
}
wchar_t *
String_Duplicate(const wchar_t *string)
{
int length;
wchar_t *copy;
if (NULL == string)
return NULL;
length = lstrlenW(string) + 1;
copy = String_Malloc(length);
if (NULL != copy)
CopyMemory(copy, string, sizeof(wchar_t) * length);
return copy;
}
char *
String_ToAnsi(unsigned int codePage, unsigned long flags, const wchar_t *string,
int stringLength, const char *defaultChar, BOOL *usedDefaultChar)
{
char *buffer;
int bufferSize;
if (stringLength < 0)
stringLength = lstrlen(string);
bufferSize = WideCharToMultiByte(codePage, flags, string, stringLength,
NULL, 0, defaultChar, usedDefaultChar);
if (0 == bufferSize)
return NULL;
buffer = AnsiString_Malloc(bufferSize + 1);
if (NULL == buffer)
return NULL;
bufferSize = WideCharToMultiByte(codePage, flags, string, stringLength,
buffer, bufferSize, defaultChar, usedDefaultChar);
if (0 == bufferSize)
{
AnsiString_Free(buffer);
return NULL;
}
buffer[bufferSize] = '\0';
return buffer;
}
size_t
String_CopyTo(wchar_t *destination, const wchar_t *source, size_t size)
{
size_t remaining;
if (FAILED(StringCchCopyExW(destination, size, source, NULL, &remaining, STRSAFE_IGNORE_NULLS)))
return 0;
return (size - remaining);
}
wchar_t *
String_FromWindowEx(HWND hwnd, size_t *lengthOut, BOOL *errorOut)
{
BOOL error;
size_t length;
wchar_t *string;
error = TRUE;
string = NULL;
length = 0;
if (NULL != hwnd)
{
length = GetWindowTextLength(hwnd);
if (0 != length ||
ERROR_SUCCESS == GetLastError())
{
string = String_Malloc(length + 1);
if(NULL != string)
{
if (0 == length)
{
string[0] = L'\0';
error = FALSE;
}
else
{
length = GetWindowText(hwnd, string, (int)length + 1);
if (0 == length && ERROR_SUCCESS != GetLastError())
{
String_Free(string);
string = NULL;
}
else
error = FALSE;
}
}
}
}
if (NULL != lengthOut)
*lengthOut = length;
if (NULL != errorOut)
*errorOut = error;
return string;
}
char *
AnsiString_Malloc(size_t size)
{
return (char*)malloc(sizeof(char) * size);
}
char *
AnsiString_ReAlloc(char *string, size_t size)
{
return (char*)realloc(string, sizeof(char) * size);
}
void
AnsiString_Free(char *string)
{
if (NULL != string)
free(string);
}
char *
AnsiString_Duplicate(const char *string)
{
char *copy;
INT length;
if (NULL == string)
return NULL;
length = lstrlenA(string) + 1;
copy = AnsiString_Malloc(length);
if (NULL != copy)
CopyMemory(copy, string, sizeof(char) * length);
return copy;
}
wchar_t *
AnsiString_ToUnicode(unsigned int codePage, unsigned long flags, const char* string, INT stringLength)
{
wchar_t *buffer;
int buffferSize;
if (NULL == string)
return NULL;
buffferSize = MultiByteToWideChar(codePage, flags, string, stringLength, NULL, 0);
if (0 == buffferSize)
return NULL;
if (stringLength > 0)
buffferSize++;
buffer = String_Malloc(buffferSize);
if (NULL == buffer)
return NULL;
if (0 == MultiByteToWideChar(codePage, flags, string, stringLength, buffer, buffferSize))
{
String_Free(buffer);
return NULL;
}
if (stringLength > 0)
buffer[buffferSize - 1] = L'\0';
return buffer;
}
wchar_t*
ResourceString_Duplicate(const wchar_t *source)
{
return (FALSE != IS_INTRESOURCE(source)) ?
(LPWSTR)source :
String_Duplicate(source);
}
void
ResourceString_Free(wchar_t *string)
{
if (FALSE == IS_INTRESOURCE(string))
String_Free(string);
}
size_t
ResourceString_CopyTo(wchar_t *destination, const wchar_t *source, size_t size)
{
if (NULL == destination)
return 0;
if (NULL == source)
{
destination[0] = L'\0';
return 0;
}
if (FALSE != IS_INTRESOURCE(source))
{
if (NULL == WASABI_API_LNG)
{
destination[0] = L'\0';
return 0;
}
WASABI_API_LNGSTRINGW_BUF((INT)(INT_PTR)source, destination, size);
return lstrlenW(destination);
}
return String_CopyTo(destination, source, size);
}
@@ -0,0 +1,82 @@
#ifndef _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_STRINGS_HEADER
#define _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_STRINGS_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#define IS_STRING_EMPTY(_string) (NULL == (_string) || L'\0' == *(_string))
wchar_t *
String_Malloc(size_t size);
wchar_t *
String_ReAlloc(wchar_t *string,
size_t size);
void
String_Free(wchar_t *string);
wchar_t *
String_Duplicate(const wchar_t *string);
char *
String_ToAnsi(unsigned int codePage,
unsigned long flags,
const wchar_t *string,
int stringLength,
const char *defaultChar,
BOOL *usedDefaultChar);
size_t
String_CopyTo(wchar_t *destination,
const wchar_t *source,
size_t size);
wchar_t *
String_FromWindowEx(HWND hwnd,
size_t *lengthOut,
BOOL *errorOut);
#define String_FromWindow(/*HWND*/ _hwnd)\
String_FromWindowEx((_hwnd), NULL, NULL)
/*
Ansi String
*/
char *
AnsiString_Malloc(size_t size);
char *
AnsiString_ReAlloc(char *string,
size_t size);
void
AnsiString_Free(char *string);
char *
AnsiString_Duplicate(const char *string);
wchar_t *
AnsiString_ToUnicode(unsigned int codePage,
unsigned long flags,
const char *string,
int stringLength);
/*
Resource String
*/
wchar_t*
ResourceString_Duplicate(const wchar_t *source);
void
ResourceString_Free(wchar_t *string);
size_t
ResourceString_CopyTo(wchar_t *destination,
const wchar_t *source,
size_t size);
#endif //_NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_STRINGS_HEADER
@@ -0,0 +1,108 @@
#include "main.h"
#include "./supportedCommand.h"
#include <strsafe.h>
DeviceSupportedCommand::DeviceSupportedCommand()
: ref(1), name(NULL), flags(DeviceCommandFlag_None)
{
}
DeviceSupportedCommand::~DeviceSupportedCommand()
{
AnsiString_Free(name);
}
HRESULT DeviceSupportedCommand::CreateInstance(const char *name, DeviceSupportedCommand **instance)
{
DeviceSupportedCommand *self;
if (NULL == instance)
return E_POINTER;
*instance = NULL;
self = new DeviceSupportedCommand();
if (NULL == self)
return E_OUTOFMEMORY;
self->name = AnsiString_Duplicate(name);
*instance = self;
return S_OK;
}
size_t DeviceSupportedCommand::AddRef()
{
return InterlockedIncrement((LONG*)&ref);
}
size_t DeviceSupportedCommand::Release()
{
if (0 == ref)
return ref;
LONG r = InterlockedDecrement((LONG*)&ref);
if (0 == r)
delete(this);
return r;
}
int DeviceSupportedCommand::QueryInterface(GUID interface_guid, void **object)
{
if (NULL == object)
return E_POINTER;
if (IsEqualIID(interface_guid, IFC_DeviceSupportedCommand))
*object = static_cast<ifc_devicesupportedcommand*>(this);
else
{
*object = NULL;
return E_NOINTERFACE;
}
if (NULL == *object)
return E_UNEXPECTED;
AddRef();
return S_OK;
}
const char *DeviceSupportedCommand::GetName()
{
return name;
}
HRESULT DeviceSupportedCommand::GetFlags(DeviceCommandFlags *flagsOut)
{
if (NULL == flagsOut)
return E_POINTER;
*flagsOut = flags;
return S_OK;
}
HRESULT DeviceSupportedCommand::SetFlags(DeviceCommandFlags mask, DeviceCommandFlags value)
{
DeviceCommandFlags temp;
temp = (flags & mask) | (mask & value);
if (temp == flags)
return S_FALSE;
flags = temp;
return S_OK;
}
#define CBCLASS DeviceSupportedCommand
START_DISPATCH;
CB(ADDREF, AddRef)
CB(RELEASE, Release)
CB(QUERYINTERFACE, QueryInterface)
CB(API_GETNAME, GetName)
CB(API_GETFLAGS, GetFlags)
END_DISPATCH;
#undef CBCLASS
@@ -0,0 +1,46 @@
#ifndef _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_SUPPORTED_COMMAND_HEADER
#define _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_SUPPORTED_COMMAND_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
#include <ifc_devicesupportedcommand.h>
class DeviceSupportedCommand : public ifc_devicesupportedcommand
{
protected:
DeviceSupportedCommand();
~DeviceSupportedCommand();
public:
static HRESULT CreateInstance(const char *name,
DeviceSupportedCommand **instance);
public:
/* Dispatchable */
size_t AddRef();
size_t Release();
int QueryInterface(GUID interface_guid, void **object);
/* ifc_devicesupportedcommand */
const char *GetName();
HRESULT GetFlags(DeviceCommandFlags *flags);
public:
HRESULT SetFlags(DeviceCommandFlags mask, DeviceCommandFlags value);
protected:
size_t ref;
char *name;
DeviceCommandFlags flags;
protected:
RECVS_DISPATCH;
};
#endif //_NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_SUPPORTED_COMMAND_HEADER
@@ -0,0 +1,555 @@
#include "main.h"
#include "./testSuite.h"
#include <strsafe.h>
TestSuite::TestSuite()
{
}
TestSuite::~TestSuite()
{
size_t index;
index = deviceList.size();
while(index--)
{
deviceList[index]->Release();
}
index = typeList.size();
while(index--)
{
typeList[index]->Release();
}
index = connectionList.size();
while(index--)
{
connectionList[index]->Release();
}
index = commandList.size();
while(index--)
{
commandList[index]->Release();
}
index = insertList.size();
while(index--)
{
AnsiString_Free(insertList[index]);
}
}
BOOL TestSuite::AddDevice(Device *device)
{
if (NULL == device)
return FALSE;
deviceList.push_back(device);
device->AddRef();
return TRUE;
}
size_t TestSuite::GetDeviceCount()
{
return deviceList.size();
}
Device *TestSuite::GetDevice(size_t index)
{
return deviceList[index];
}
static int
String_RemoveCounter(wchar_t *string)
{
int len;
len = lstrlenW(string);
if (len > 3)
{
int cutoff = 0;
if (string[len-1] == L')')
{
WORD charType;
cutoff = 1;
while(len > cutoff &&
FALSE != GetStringTypeW(CT_CTYPE1, string + (len - 1) - cutoff, 1, &charType) &&
0 != (C1_DIGIT & charType))
{
cutoff++;
}
if (len > cutoff &&
cutoff > 1 &&
L'(' == string[len - 1 - cutoff])
{
cutoff++;
if (len > cutoff &&
L' ' == string[len - 1 - cutoff])
{
string[len - 1 - cutoff] = L'\0';
len -= (cutoff + 1);
}
}
}
}
return len;
}
static int
AnsiString_RemoveCounter(char *string)
{
int len;
len = lstrlenA(string);
if (len > 3)
{
int cutoff = 0;
if (string[len-1] == ')')
{
WORD charType;
cutoff = 1;
while(len > cutoff &&
FALSE != GetStringTypeA(LOCALE_SYSTEM_DEFAULT, CT_CTYPE1, string + (len - 1) - cutoff, 1, &charType) &&
0 != (C1_DIGIT & charType))
{
cutoff++;
}
if (len > cutoff &&
cutoff > 1 &&
'(' == string[len - 1 - cutoff])
{
cutoff++;
if (len > cutoff &&
' ' == string[len - 1 - cutoff])
{
string[len - 1 - cutoff] = '\0';
len -= (cutoff + 1);
}
}
}
}
return len;
}
Device *TestSuite::CreateDeviceCopy(Device *source)
{
const char *name;
size_t index, counter;
char buffer[1024];
wchar_t *displayName;
BOOL found;
Device *destination;
int length;
if (NULL == source)
return NULL;
found = FALSE;
counter = 0;
name = source->GetName();
StringCbCopyA(buffer, sizeof(buffer), name);
length = AnsiString_RemoveCounter(buffer);
for (;;)
{
if (0 != counter)
StringCbPrintfA(buffer + length, sizeof(buffer) - length, " (%d)", counter);
found = TRUE;
index = deviceList.size();
while(index--)
{
if (CSTR_EQUAL == CompareStringA(CSTR_INVARIANT, 0, deviceList[index]->GetName(), -1, buffer, -1))
{
found = FALSE;
break;
}
}
if (FALSE != found)
break;
else
counter++;
}
if (FAILED(Device::CreateInstance(buffer, source->GetType(), source->GetConnection(), &destination)))
return NULL;
source->CopyTo(destination);
source->GetDisplayName((wchar_t*)buffer, sizeof(buffer)/sizeof(wchar_t));
displayName = (wchar_t*)buffer;
length = String_RemoveCounter(displayName);
if (0 != counter)
StringCchPrintf(displayName + length, sizeof(buffer)/sizeof(wchar_t) - length, L" (%d)", counter);
destination->SetDisplayName(displayName);
return destination;
}
Device *TestSuite::GetRandomDevice()
{
size_t index;
Device *device;
LARGE_INTEGER perfCounter;
if (0 == deviceList.size())
return NULL;
if (FALSE != QueryPerformanceCounter(&perfCounter))
srand(perfCounter.LowPart);
else
srand(GetTickCount());
index = (size_t)((double)rand()/(RAND_MAX + 1) * deviceList.size());
device = deviceList[index];
if (S_OK == device->IsConnected())
{
size_t search;
for(search = index + 1; search < deviceList.size(); search++)
{
device = deviceList[search];
if (S_FALSE == device->IsConnected())
return device;
}
search = index;
while(search--)
{
device = deviceList[search];
if (S_FALSE == device->IsConnected())
return device;
}
device = CreateDeviceCopy(deviceList[index]);
if (NULL != device)
{
size_t totalSpace, usedSpace;
totalSpace = (size_t)((double)rand()/(RAND_MAX + 1) * 1000);
usedSpace = (size_t)((double)rand()/(RAND_MAX + 1) * totalSpace);
device->SetTotalSpace(totalSpace);
device->SetUsedSpace(usedSpace);
device->Disconnect();
device->Detach(NULL);
AddDevice(device);
}
}
return device;
}
BOOL TestSuite::AddType(ifc_devicetype *type)
{
if (NULL == type)
return FALSE;
typeList.push_back(type);
type->AddRef();
return TRUE;
}
size_t TestSuite::GetTypeCount()
{
return typeList.size();
}
ifc_devicetype *TestSuite::GetType(size_t index)
{
return typeList[index];
}
BOOL TestSuite::RegisterTypes(api_devicemanager *manager)
{
if (NULL == manager)
return FALSE;
if (0 != typeList.size())
manager->TypeRegister((ifc_devicetype**)typeList.begin(), typeList.size());
return TRUE;
}
BOOL TestSuite::UnregisterTypes(api_devicemanager *manager)
{
size_t index;
if (NULL == manager)
return FALSE;
index = typeList.size();
while(index--)
{
manager->TypeUnregister(typeList[index]->GetName());
}
return TRUE;
}
BOOL TestSuite::SetIconBase(const wchar_t *path)
{
size_t index;
Device *device;
ifc_devicetype *type;
ifc_devicetypeeditor *typeEditor;
ifc_deviceiconstore *iconStore;
ifc_deviceconnection *connection;
ifc_deviceconnectioneditor *connectionEditor;
ifc_devicecommand *command;
ifc_devicecommandeditor *commandEditor;
index = deviceList.size();
while(index--)
{
device = deviceList[index];
device->SetIconBase(path);
}
index = typeList.size();
while(index--)
{
type = typeList[index];
if (SUCCEEDED(type->QueryInterface(IFC_DeviceTypeEditor, (void**)&typeEditor)))
{
if(SUCCEEDED(typeEditor->GetIconStore(&iconStore)))
{
iconStore->SetBasePath(path);
iconStore->Release();
}
typeEditor->Release();
}
}
index = commandList.size();
while(index--)
{
command = commandList[index];
if (SUCCEEDED(command->QueryInterface(IFC_DeviceCommandEditor, (void**)&commandEditor)))
{
if(SUCCEEDED(commandEditor->GetIconStore(&iconStore)))
{
iconStore->SetBasePath(path);
iconStore->Release();
}
commandEditor->Release();
}
}
index = connectionList.size();
while(index--)
{
connection = connectionList[index];
if (SUCCEEDED(connection->QueryInterface(IFC_DeviceConnectionEditor, (void**)&connectionEditor)))
{
if(SUCCEEDED(connectionEditor->GetIconStore(&iconStore)))
{
iconStore->SetBasePath(path);
iconStore->Release();
}
connectionEditor->Release();
}
}
return S_OK;
}
BOOL TestSuite::SetConnectList(char **devices, size_t count)
{
size_t index;
char *name;
index = insertList.size();
if (index > 0)
{
while(index--)
{
name = insertList[index];
AnsiString_Free(name);
}
insertList.clear();
}
for(index = 0; index < count; index++)
{
name = AnsiString_Duplicate(devices[index]);
if (NULL != name)
insertList.push_back(name);
}
return TRUE;
}
Device *TestSuite::GetDeviceByName(const char *name)
{
size_t index;
Device *device;
for (index = 0; index < deviceList.size(); index++)
{
device = deviceList[index];
if (CSTR_EQUAL == CompareStringA(CSTR_INVARIANT, NORM_IGNORECASE, name, -1, device->GetName(), -1))
return device;
}
return NULL;
}
BOOL TestSuite::RegisterDevices(api_devicemanager *manager)
{
size_t index;
const char *name;
Device *device;
if (NULL == manager)
return FALSE;
for (index = 0; index < insertList.size(); index++)
{
name = insertList[index];
device = GetDeviceByName(name);
if (NULL != device)
{
manager->DeviceRegister((ifc_device**)&device, 1);
device->Connect();
}
}
return TRUE;
}
BOOL TestSuite::UnregisterDevices(api_devicemanager *manager)
{
size_t index;
Device *device;
if (NULL == manager)
return FALSE;
index = deviceList.size();
while(index--)
{
device = deviceList[index];
if (S_OK == device->IsConnected())
{
device->Disconnect();
manager->DeviceUnregister(device->GetName());
}
}
return TRUE;
}
BOOL TestSuite::AddConnection(ifc_deviceconnection *connection)
{
if (NULL == connection)
return FALSE;
connectionList.push_back(connection);
connection->AddRef();
return TRUE;
}
size_t TestSuite::GetConnectionCount()
{
return connectionList.size();
}
ifc_deviceconnection *TestSuite::GetConnection(size_t index)
{
return connectionList[index];
}
BOOL TestSuite::RegisterConnections(api_devicemanager *manager)
{
if (NULL == manager)
return FALSE;
if (0 != connectionList.size())
manager->ConnectionRegister((ifc_deviceconnection**)connectionList.begin(), connectionList.size());
return TRUE;
}
BOOL TestSuite::UnregisterConnections(api_devicemanager *manager)
{
size_t index;
if (NULL == manager)
return FALSE;
index = connectionList.size();
while(index--)
{
manager->ConnectionUnregister(connectionList[index]->GetName());
}
return TRUE;
}
BOOL TestSuite::AddCommand(ifc_devicecommand *command)
{
if (NULL == command)
return FALSE;
commandList.push_back(command);
command->AddRef();
return TRUE;
}
size_t TestSuite::GetCommandCount()
{
return commandList.size();
}
ifc_devicecommand *TestSuite::GetCommand(size_t index)
{
return commandList[index];
}
BOOL TestSuite::RegisterCommands(api_devicemanager *manager)
{
if (NULL == manager)
return FALSE;
if (0 != commandList.size())
manager->CommandRegister((ifc_devicecommand**)commandList.begin(), commandList.size());
return TRUE;
}
BOOL TestSuite::UnregisterCommands(api_devicemanager *manager)
{
size_t index;
if (NULL == manager)
return FALSE;
index = commandList.size();
while(index--)
{
manager->CommandUnregister(commandList[index]->GetName());
}
return TRUE;
}
@@ -0,0 +1,67 @@
#ifndef _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_TEST_SUITE_HEADER
#define _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_TEST_SUITE_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
#include <vector>
#include "./device.h"
class TestSuite
{
public:
TestSuite();
~TestSuite();
public:
BOOL AddDevice(Device *device);
size_t GetDeviceCount();
Device *GetDevice(size_t index);
Device *GetRandomDevice();
Device *CreateDeviceCopy(Device *source);
Device *GetDeviceByName(const char *name);
BOOL RegisterDevices(api_devicemanager *manager);
BOOL UnregisterDevices(api_devicemanager *manager);
BOOL AddType(ifc_devicetype *type);
size_t GetTypeCount();
ifc_devicetype *GetType(size_t index);
BOOL RegisterTypes(api_devicemanager *manager);
BOOL UnregisterTypes(api_devicemanager *manager);
BOOL AddConnection(ifc_deviceconnection *connection);
size_t GetConnectionCount();
ifc_deviceconnection *GetConnection(size_t index);
BOOL RegisterConnections(api_devicemanager *manager);
BOOL UnregisterConnections(api_devicemanager *manager);
BOOL AddCommand(ifc_devicecommand *command);
size_t GetCommandCount();
ifc_devicecommand *GetCommand(size_t index);
BOOL RegisterCommands(api_devicemanager *manager);
BOOL UnregisterCommands(api_devicemanager *manager);
BOOL SetIconBase(const wchar_t *path);
BOOL SetConnectList(char **devices, size_t count);
private:
typedef std::vector<Device*> DeviceList;
typedef std::vector<ifc_devicetype*> TypeList;
typedef std::vector<ifc_deviceconnection*> ConnectionList;
typedef std::vector<ifc_devicecommand*> CommandList;
typedef std::vector<char*> NameList;
private:
DeviceList deviceList;
TypeList typeList;
ConnectionList connectionList;
CommandList commandList;
NameList insertList;
};
#endif // _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_TEST_SUITE_HEADER
@@ -0,0 +1,226 @@
#include "main.h"
#include "./testSuiteLoader.h"
#include "../../xml/obj_xml.h"
#include <api/service/waservicefactory.h>
#include <strsafe.h>
typedef void (CALLBACK *LOADERTAGCALLBACK)(TestSuiteLoader* /*loader*/, const wchar_t* /*value*/);
typedef struct LOADERTAG
{
const wchar_t *name;
LOADERTAGCALLBACK callback;
} LOADERTAG;
static void CALLBACK
LoaderTag_ImageBase(TestSuiteLoader *loader, const wchar_t *value)
{
String_Free(loader->imageBase);
loader->imageBase = String_Duplicate(value);
}
static void CALLBACK
LoaderTag_Connect(TestSuiteLoader *loader, const wchar_t *value)
{
if (IS_STRING_EMPTY(value))
return;
const wchar_t *block, *cursor;
char *name;
size_t length;
block = value;
cursor = block;
for(;;)
{
if (L'\0' == *cursor ||
L';' == *cursor ||
L',' == *cursor)
{
if (block < cursor)
{
length = cursor - block;
name = String_ToAnsi(CP_UTF8, 0, block, (int)length, NULL, NULL);
if (NULL != name)
loader->connectList.push_back(name);
}
if (L'\0' == *cursor)
break;
block = cursor + 1;
}
cursor++;
}
//loader->SetImageBase(value);
}
static const LOADERTAG knownTags[LOADER_TAG_MAX] =
{
{L"imageBase", LoaderTag_ImageBase},
{L"connect", LoaderTag_Connect},
};
TestSuiteLoader::TestSuiteLoader()
: imageBase(NULL)
{
}
TestSuiteLoader::~TestSuiteLoader()
{
size_t index;
index = connectList.size();
while(index--)
{
AnsiString_Free(connectList[index]);
}
String_Free(imageBase);
}
BOOL TestSuiteLoader::Load(const wchar_t *path, TestSuite *testSuite)
{
BOOL result;
HANDLE fileHandle;
obj_xml *reader;
if (NULL == testSuite)
return FALSE;
if (NULL == path || L'\0' == *path)
return FALSE;
fileHandle = CreateFile(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (INVALID_HANDLE_VALUE == fileHandle)
return FALSE;
result = FALSE;
if (NULL != WASABI_API_SVC)
{
waServiceFactory *sf = WASABI_API_SVC->service_getServiceByGuid(obj_xmlGUID);
reader = (NULL != sf) ? (obj_xml*)sf->getInterface() : NULL;
if (NULL != reader)
{
if (OBJ_XML_SUCCESS == reader->xmlreader_open())
{
reader->xmlreader_registerCallback(L"testprovider\fimageBase", this);
reader->xmlreader_registerCallback(L"testprovider\fconnect", this);
ZeroMemory(hitList, sizeof(hitList));
deviceParser.Begin(reader, testSuite);
typeParser.Begin(reader, testSuite);
connectionParser.Begin(reader, testSuite);
commandParser.Begin(reader, testSuite);
result = FeedFile(reader, fileHandle, 8192);
deviceParser.End();
typeParser.End();
connectionParser.End();
commandParser.End();
reader->xmlreader_close();
testSuite->SetIconBase(imageBase);
testSuite->SetConnectList(connectList.begin(), connectList.size());
}
sf->releaseInterface(reader);
}
}
CloseHandle(fileHandle);
return result;
}
BOOL TestSuiteLoader::FeedFile(obj_xml *reader, HANDLE fileHandle, DWORD bufferSize)
{
BOOL result;
DWORD read;
BYTE *buffer;
int readerCode;
if (NULL == reader ||
INVALID_HANDLE_VALUE == fileHandle ||
0 == bufferSize)
{
return FALSE;
}
buffer = (BYTE*)malloc(bufferSize);
if (NULL == buffer)
return FALSE;
readerCode = OBJ_XML_SUCCESS;
result = TRUE;
for(;;)
{
if (FALSE == ReadFile(fileHandle, buffer, bufferSize, &read, NULL) || 0 == read)
{
result = FALSE;
if (0 == read && OBJ_XML_SUCCESS == readerCode)
reader->xmlreader_feed(0, 0);
break;
}
readerCode = reader->xmlreader_feed(buffer, read);
if (OBJ_XML_SUCCESS != readerCode)
{
result = FALSE;
break;
}
}
free(buffer);
return result;
}
void TestSuiteLoader::Event_XmlStartElement(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params)
{
elementString.Clear();
}
void TestSuiteLoader::Event_XmlEndElement(const wchar_t *xmlpath, const wchar_t *xmltag)
{
for (size_t i = 0; i < LOADER_TAG_MAX; i++)
{
if (FALSE == hitList[i] &&
CSTR_EQUAL == CompareString(CSTR_INVARIANT, NORM_IGNORECASE, knownTags[i].name, -1, xmltag, -1))
{
knownTags[i].callback(this, elementString.Get());
hitList[i] = TRUE;
break;
}
}
}
void TestSuiteLoader::Event_XmlCharData(const wchar_t *xmlpath, const wchar_t *xmltag, const wchar_t *value)
{
elementString.Append(value);
}
void TestSuiteLoader::Event_XmlError(int linenum, int errcode, const wchar_t *errstr)
{
elementString.Clear();
}
#define CBCLASS TestSuiteLoader
START_DISPATCH;
VCB(ONSTARTELEMENT, Event_XmlStartElement)
VCB(ONENDELEMENT, Event_XmlEndElement)
VCB(ONCHARDATA, Event_XmlCharData)
VCB(ONERROR, Event_XmlError)
END_DISPATCH;
#undef CBCLASS
@@ -0,0 +1,60 @@
#ifndef _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_TEST_SUITE_LOADER_HEADER
#define _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_TEST_SUITE_LOADER_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
#include "../../xml/ifc_xmlreadercallback.h"
#include <vector>
#include "./DeviceNodeParser.h"
#include "./DeviceTypeNodeParser.h"
#include "./DeviceConnectionNodeParser.h"
#include "./DeviceCommandNodeParser.h"
class obj_xml;
#define LOADER_TAG_MAX 2
class TestSuiteLoader : public ifc_xmlreadercallback
{
public:
TestSuiteLoader();
~TestSuiteLoader();
public:
BOOL Load(const wchar_t *path, TestSuite *testSuite);
private:
BOOL FeedFile(obj_xml *reader, HANDLE hFile, DWORD bufferSize);
void Event_XmlStartElement(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params);
void Event_XmlEndElement(const wchar_t *xmlpath, const wchar_t *xmltag);
void Event_XmlCharData(const wchar_t *xmlpath, const wchar_t *xmltag, const wchar_t *value);
void Event_XmlError(int linenum, int errcode, const wchar_t *errstr);
protected:
friend static void CALLBACK LoaderTag_ImageBase(TestSuiteLoader *loader, const wchar_t *value);
friend static void CALLBACK LoaderTag_Connect(TestSuiteLoader *loader, const wchar_t *value);
protected:
typedef std::vector<char*> NameList;
protected:
StringBuilder elementString;
DeviceNodeParser deviceParser;
DeviceTypeNodeParser typeParser;
DeviceConnectionNodeParser connectionParser;
DeviceCommandNodeParser commandParser;
BOOL hitList[LOADER_TAG_MAX];
wchar_t *imageBase;
NameList connectList;
protected:
RECVS_DISPATCH;
};
#endif // _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_TEST_SUITE_LOADER_HEADER
@@ -0,0 +1,244 @@
<?xml version="1.0" encoding="UTF-8"?>
<testprovider>
<imageBase>c:\winamp\ml_devices\resources\food</imageBase>
<connect>iconTest;apple;banana;grape;pear;pepper;eggplant;cucumber;carrot</connect>
<connections>
<connection name="usb">
<displayName>USB</displayName>
<icon>..\connections\usb.png</icon>
</connection>
<connection name="wifi">
<displayName>Wi-Fi</displayName>
<icon>..\connections\wifi.png</icon>
</connection>
<connection name="bluetooth">
<displayName>Bluetooth</displayName>
<icon>..\connections\bluetooth.png</icon>
</connection>
</connections>
<types>
<type name="vegetables">
<displayName>Vegetables</displayName>
<icon>vegetables.png</icon>
</type>
<type name="fruits">
<displayName>Fruits</displayName>
<icon>fruits.png</icon>
</type>
<type name="grains">
<displayName>Grains</displayName>
<icon>grains.png</icon>
</type>
</types>
<commands>
<command name="sync">
<displayName>&amp;Sync</displayName>
<description>Sync things</description>
<icon>..\commands\sync.png</icon>
</command>
<command name="settings">
<displayName>Se&amp;ttings</displayName>
<description>Open settings page</description>
<icon>..\commands\settings.png</icon>
</command>
<command name="detach">
<displayName>&amp;Detach</displayName>
<description>Detach device</description>
<icon>..\commands\detach.png</icon>
</command>
<command name="eject">
<displayName>&amp;Eject</displayName>
<description>Eject device</description>
<icon>..\commands\eject.png</icon>
</command>
</commands>
<devices>
<device name="iconTest" type="test">
<connection></connection>
<displayName>Icon Test</displayName>
<icon width="24" height="32">..\zoom\24x32.png</icon>
<icon width="48" height="64">..\zoom\48x64.png</icon>
<icon width="96" height="128">..\zoom\96x128.png</icon>
<icon width="192" height="256">..\zoom\192x256.png</icon>
<command primary="1" disabled="0">sync</command>
<command primary="0" disabled="0" hidden="0" group="1">settings</command>
<command primary="0">detach</command>
<command disabled="1" hidden="0">eject</command>
<totalSpace>909242</totalSpace>
<usedSpace>0</usedSpace>
<hidden>0</hidden>
<model>Icon Test v1.0</model>
<status>Icon Test status string</status>
</device>
<device name="apple" type="fruits">
<connection>wifi</connection>
<displayName>Dilicious&#10;Apple</displayName>
<icon>apple.png</icon>
<totalSpace>100</totalSpace>
<usedSpace>0</usedSpace>
<hidden>0</hidden>
<model>iApple 2</model>
<command primary="1">sync</command>
<command group="1">eject</command>
</device>
<device name="banana" type="fruits">
<connection>usb</connection>
<displayName>Banana</displayName>
<icon>banana.png</icon>
<totalSpace>100</totalSpace>
<usedSpace>0</usedSpace>
<hidden>0</hidden>
<model>iBanana 2</model>
<command primary="1">sync</command>
<command group="1">eject</command>
</device>
<device name="peach" type="fruits">
<connection>bluetooth</connection>
<displayName>Peach</displayName>
<icon>peach.png</icon>
<totalSpace>100</totalSpace>
<usedSpace>0</usedSpace>
<hidden>0</hidden>
<model>iPeach 2</model>
<command primary="1">sync</command>
<command group="1">eject</command>
</device>
<device name="orange" type="fruits">
<connection>usb</connection>
<displayName>Orange</displayName>
<icon>orange.png</icon>
<totalSpace>100</totalSpace>
<usedSpace>0</usedSpace>
<hidden>0</hidden>
<model>iOrange 2</model>
<command primary="1">sync</command>
<command group="1">eject</command>
</device>
<device name="pear" type="fruits">
<connection>wifi</connection>
<displayName>Pear</displayName>
<icon>pear.png</icon>
<totalSpace>100</totalSpace>
<usedSpace>0</usedSpace>
<hidden>0</hidden>
<model>iPear 2</model>
<command primary="1">sync</command>
<command group="1">eject</command>
</device>
<device name="grape" type="fruits">
<connection>bluetooth</connection>
<displayName>Grape</displayName>
<icon>grape.png</icon>
<totalSpace>100</totalSpace>
<usedSpace>0</usedSpace>
<hidden>0</hidden>
<model>iGrape 2</model>
<command primary="1">sync</command>
<command group="1">eject</command>
</device>
<device name="lemon" type="fruits">
<connection>usb</connection>
<displayName>Lemon</displayName>
<icon>lemon.png</icon>
<totalSpace>100</totalSpace>
<usedSpace>0</usedSpace>
<hidden>0</hidden>
<model>iLemon 2</model>
<command primary="1">sync</command>
<command group="1">eject</command>
</device>
<device name="carrot" type="vegetables">
<connection>wifi</connection>
<displayName>Carrot</displayName>
<icon>carrot.png</icon>
<totalSpace>100</totalSpace>
<usedSpace>0</usedSpace>
<hidden>0</hidden>
<command primary="1">sync</command>
</device>
<device name="broccoli" type="vegetables">
<connection>bluetooth</connection>
<displayName>Broccoli</displayName>
<icon>broccoli.png</icon>
<totalSpace>100</totalSpace>
<usedSpace>0</usedSpace>
<hidden>0</hidden>
<command primary="1">sync</command>
</device>
<device name="eggplant" type="vegetables">
<connection>usb</connection>
<displayName>Eggplant</displayName>
<icon>eggplant.png</icon>
<totalSpace>100</totalSpace>
<usedSpace>0</usedSpace>
<hidden>0</hidden>
<command primary="1">sync</command>
</device>
<device name="cucumber" type="vegetables">
<connection>wifi</connection>
<displayName>Cucumber</displayName>
<icon>cucumber.png</icon>
<totalSpace>0</totalSpace>
<usedSpace>0</usedSpace>
<hidden>0</hidden>
<command primary="1">sync</command>
</device>
<device name="pepper" type="vegetables">
<connection>bluetooth</connection>
<displayName>Pepper</displayName>
<icon>pepper.png</icon>
<totalSpace>0</totalSpace>
<usedSpace>0</usedSpace>
<hidden>0</hidden>
<command primary="1">sync</command>
</device>
<device name="bread" type="grains">
<connection>usb</connection>
<displayName>Bread</displayName>
<icon>bread.png</icon>
<totalSpace>100</totalSpace>
<usedSpace>0</usedSpace>
<hidden>0</hidden>
</device>
<device name="pasta" type="grains">
<connection>wifi</connection>
<displayName>Pasta</displayName>
<icon>pasta.png</icon>
<totalSpace>100</totalSpace>
<usedSpace>0</usedSpace>
<hidden>0</hidden>
</device>
<device name="rice" type="grains">
<connection>bluetooth</connection>
<displayName>Rice</displayName>
<icon>rice.png</icon>
<totalSpace>100</totalSpace>
<usedSpace>0</usedSpace>
<hidden>0</hidden>
</device>
<device name="cereal" type="grains">
<connection>usb</connection>
<displayName>Cereal</displayName>
<icon>cereal.png</icon>
<totalSpace>100</totalSpace>
<usedSpace>0</usedSpace>
<hidden>0</hidden>
</device>
<device name="muffin" type="grains">
<connection>wifi</connection>
<displayName>Muffin</displayName>
<icon>muffin.png</icon>
<totalSpace>100</totalSpace>
<usedSpace>0</usedSpace>
<hidden>0</hidden>
</device>
<device name="pretzel" type="grains">
<connection>bluetooth</connection>
<displayName>Pretzel</displayName>
<icon>pretzel.png</icon>
<totalSpace>100</totalSpace>
<usedSpace>0</usedSpace>
<hidden>0</hidden>
</device>
</devices>
</testprovider>
@@ -0,0 +1,139 @@
#include "main.h"
#include "./wasabi.h"
#include <api/service/waservicefactory.h>
api_service *WASABI_API_SVC = NULL;
api_application *WASABI_API_APP = NULL;
api_language *WASABI_API_LNG = NULL;
api_devicemanager *WASABI_API_DEVICES = NULL;
HINSTANCE WASABI_API_LNG_HINST = NULL;
HINSTANCE WASABI_API_ORIG_HINST = NULL;
static unsigned long wasabiReference = 0;
static BOOL defaultServicesLoaded = FALSE;
static void
Wasabi_Uninitialize()
{
if (NULL != WASABI_API_SVC)
{
Wasabi_ReleaseInterface(applicationApiServiceGuid, WASABI_API_APP);
Wasabi_ReleaseInterface(languageApiGUID, WASABI_API_LNG);
Wasabi_ReleaseInterface(DeviceManagerGUID, WASABI_API_DEVICES);
}
WASABI_API_SVC = NULL;
WASABI_API_APP = NULL;
WASABI_API_LNG = NULL;
WASABI_API_DEVICES = NULL;
defaultServicesLoaded = FALSE;
}
BOOL
Wasabi_Initialize(HINSTANCE instance, api_service *serviceMngr)
{
if (NULL != WASABI_API_SVC)
return FALSE;
defaultServicesLoaded = FALSE;
WASABI_API_SVC = serviceMngr;
if ((api_service*)1 == WASABI_API_SVC)
WASABI_API_SVC = NULL;
if (NULL == WASABI_API_SVC)
return FALSE;
WASABI_API_APP = NULL;
WASABI_API_DEVICES = NULL;
WASABI_API_LNG = NULL;
WASABI_API_ORIG_HINST = instance;
WASABI_API_LNG_HINST = WASABI_API_ORIG_HINST;
Wasabi_AddRef();
return TRUE;
}
BOOL
Wasabi_InitializeFromWinamp(HINSTANCE instance, HWND winampWindow)
{
api_service *serviceMngr;
serviceMngr = (api_service*)SENDWAIPC(winampWindow, IPC_GET_API_SERVICE, 0);
return Wasabi_Initialize(instance, serviceMngr);
}
BOOL
Wasabi_LoadDefaultServices(void)
{
if (NULL == WASABI_API_SVC)
return FALSE;
if (FALSE != defaultServicesLoaded)
return FALSE;
WASABI_API_APP = Wasabi_QueryInterface(api_application, applicationApiServiceGuid);
WASABI_API_DEVICES = Wasabi_QueryInterface(api_devicemanager, DeviceManagerGUID);
WASABI_API_LNG = Wasabi_QueryInterface(api_language, languageApiGUID);
if (NULL != WASABI_API_LNG)
{
WASABI_API_LNG_HINST = WASABI_API_LNG->StartLanguageSupport(WASABI_API_ORIG_HINST,
PLUGIN_LANGUAGE_ID);
}
defaultServicesLoaded = TRUE;
return TRUE;
}
unsigned long
Wasabi_AddRef(void)
{
return InterlockedIncrement((LONG*)&wasabiReference);
}
unsigned long
Wasabi_Release(void)
{
if (0 == wasabiReference)
return wasabiReference;
LONG r = InterlockedDecrement((LONG*)&wasabiReference);
if (0 == r)
{
Wasabi_Uninitialize();
}
return r;
}
void *
Wasabi_QueryInterface0(const GUID &interfaceGuid)
{
waServiceFactory *serviceFactory;
if (NULL == WASABI_API_SVC)
return NULL;
serviceFactory = WASABI_API_SVC->service_getServiceByGuid(interfaceGuid);
if (NULL == serviceFactory)
return NULL;
return serviceFactory->getInterface();
}
void
Wasabi_ReleaseInterface0(const GUID &interfaceGuid, void *interfaceInstance)
{
waServiceFactory *serviceFactory;
if (NULL == WASABI_API_SVC)
return;
serviceFactory = WASABI_API_SVC->service_getServiceByGuid(interfaceGuid);
if (NULL == serviceFactory)
return;
serviceFactory->releaseInterface(interfaceInstance);
}
@@ -0,0 +1,57 @@
#ifndef _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_WASABI_HEADER
#define _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_WASABI_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <api/service/api_service.h>
extern api_service *wasabiManager;
#define WASABI_API_SVC wasabiManager
#include <api/application/api_application.h>
#define WASABI_API_APP applicationApi
#include "../Agave/Language/api_language.h"
#include "../../devices/api_devicemanager.h"
extern api_devicemanager *deviceManagerApi;
#define WASABI_API_DEVICES deviceManagerApi
BOOL
Wasabi_Initialize(HINSTANCE instance,
api_service *serviceMngr);
BOOL
Wasabi_InitializeFromWinamp(HINSTANCE instance,
HWND winampWindow);
BOOL
Wasabi_LoadDefaultServices(void);
unsigned long
Wasabi_AddRef(void);
unsigned long
Wasabi_Release(void);
void *
Wasabi_QueryInterface0(const GUID &interfaceGuid);
#define Wasabi_QueryInterface(_interfaceType, _interfaceGuid)\
((##_interfaceType*)Wasabi_QueryInterface0(_interfaceGuid))
void
Wasabi_ReleaseInterface0(const GUID &interfaceGuid,
void *interfaceInstance);
#define Wasabi_ReleaseInterface(_interfaceGuid, _interfaceInstance)\
(Wasabi_ReleaseInterface0((_interfaceGuid), (_interfaceInstance)))
#define Wasabi_ReleaseObject(_object)\
{if (NULL != (_object)) {((Dispatchable*)(_object))->Release();}}
#endif // _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_WASABI_HEADER
+313
View File
@@ -0,0 +1,313 @@
#include "main.h"
#include "./graphics.h"
BYTE
Graphics_GetSysFontQuality()
{
BOOL smoothingEnabled;
if (FALSE == SystemParametersInfoW(SPI_GETFONTSMOOTHING, 0, &smoothingEnabled, 0) ||
FALSE == smoothingEnabled)
{
return DEFAULT_QUALITY;
}
OSVERSIONINFOW vi;
vi.dwOSVersionInfoSize = sizeof(vi);
if (FALSE == GetVersionExW(&vi))
return DEFAULT_QUALITY;
if (vi.dwMajorVersion > 5 || (vi.dwMajorVersion == 5 && vi.dwMinorVersion >= 1))
{
UINT smootingType;
if (FALSE == SystemParametersInfoW(SPI_GETFONTSMOOTHINGTYPE, 0, &smootingType, 0))
return DEFAULT_QUALITY;
if (FE_FONTSMOOTHINGCLEARTYPE == smootingType)
return CLEARTYPE_NATURAL_QUALITY/*CLEARTYPE_QUALITY*/;
}
return ANTIALIASED_QUALITY;
}
HFONT
Graphics_CreateSysFont()
{
LOGFONTW lf = {0};
HFONT font = NULL;
if (FALSE == SystemParametersInfoW(SPI_GETICONTITLELOGFONT, sizeof(lf), &lf, 0))
return NULL;
lf.lfQuality = Graphics_GetSysFontQuality();
font = CreateFontIndirectW(&lf);
return font;
}
HFONT
Graphics_DuplicateFont(HFONT sourceFont, INT heightDeltaPt, BOOL forceBold, BOOL systemQuality)
{
LOGFONTW lf = {0};
if (NULL == sourceFont)
return NULL;
if (sizeof(lf) != GetObjectW(sourceFont, sizeof(lf), &lf))
return NULL;
if (0 != heightDeltaPt)
{
HDC hdcTmp = NULL, hdc = GetDCEx(NULL, NULL, DCX_WINDOW | DCX_CACHE | DCX_NORESETATTRS);
if (NULL != hdc)
{
hdcTmp = CreateCompatibleDC(hdc);
ReleaseDC(NULL, hdc);
}
if (NULL == hdcTmp)
return NULL;
LONG pixelsY = GetDeviceCaps(hdcTmp, LOGPIXELSY);
HFONT prevFont = SelectFont(hdcTmp, sourceFont);
TEXTMETRICW tm = {0};
if (FALSE != GetTextMetricsW(hdcTmp, &tm))
{
INT basePt = MulDiv(tm.tmHeight - tm.tmInternalLeading, 96, pixelsY);
lf.lfHeight = -MulDiv((basePt + heightDeltaPt), pixelsY, 96);
}
SelectObject(hdcTmp, prevFont);
DeleteDC(hdcTmp);
}
if (FALSE != systemQuality)
lf.lfQuality = Graphics_GetSysFontQuality();
if (FALSE != forceBold && lf.lfWeight < FW_BOLD)
lf.lfWeight = FW_BOLD;
return CreateFontIndirectW(&lf);
}
long
Graphics_GetFontHeight(HDC hdc)
{
TEXTMETRICW tm;
if (FALSE == GetTextMetricsW(hdc, &tm))
return 0;
return tm.tmHeight;
}
long
Graphics_GetAveStrWidth(HDC hdc, UINT cchLen)
{
const char szTest[] =
{
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P', 'Q','R','S','T','U','V','W','X','Y','Z',
'a','b','c','d','e','f','g','h','i','j','k','l', 'm','n','o','p','q','r','s','t','u','v','w','x','y','z'
};
SIZE textSize;
if (FALSE == GetTextExtentPointA(hdc, szTest, ARRAYSIZE(szTest) -1, &textSize))
return 0;
LONG result;
if (1 == cchLen)
{
result = (textSize.cx + ARRAYSIZE(szTest)/2)/ARRAYSIZE(szTest);
}
else
{
result = MulDiv(cchLen, textSize.cx + ARRAYSIZE(szTest)/2, ARRAYSIZE(szTest));
if (0 != result)
{
TEXTMETRICW tm;
if (FALSE != GetTextMetricsW(hdc, &tm))
result += tm.tmOverhang;
}
}
return result;
}
BOOL
Graphics_GetWindowBaseUnits(HWND hwnd, LONG *baseUnitX, LONG *baseUnitY)
{
BOOL result;
result = FALSE;
if (NULL != hwnd)
{
HDC hdc = GetDCEx(hwnd, NULL, DCX_CACHE | DCX_NORESETATTRS);
if (NULL != hdc)
{
TEXTMETRICW tm;
HFONT font, prevFont;
font = (HFONT)SNDMSG(hwnd, WM_GETFONT, 0, 0L);
prevFont = SelectFont(hdc, font);
if (FALSE != GetTextMetricsW(hdc, &tm))
{
if (NULL != baseUnitX)
*baseUnitX = Graphics_GetAveStrWidth(hdc, 1);
if (NULL != baseUnitY)
*baseUnitY = tm.tmHeight;
result = TRUE;
}
SelectFont(hdc, prevFont);
ReleaseDC(hwnd, hdc);
}
}
return result;
}
typedef int (*SkinColorFunc)(int idx);
COLORREF Graphics_GetSkinColor(unsigned int colorIndex)
{
static SkinColorFunc GetSkinColor = NULL;
if (NULL == GetSkinColor)
{
GetSkinColor = (SkinColorFunc)SENDMLIPC(Plugin_GetLibraryWindow(), ML_IPC_SKIN_WADLG_GETFUNC, 1);
if (NULL == GetSkinColor)
return RGB(255, 0, 255);
}
return GetSkinColor(colorIndex);
}
COLORREF
Graphics_BlendColors(COLORREF rgbTop, COLORREF rgbBottom, INT alpha)
{
if (alpha > 254) return rgbTop;
if (alpha < 0) return rgbBottom;
WORD k = (WORD)(((255 - alpha)*255 + 127)/255);
return RGB( (GetRValue(rgbTop)*alpha + k*GetRValue(rgbBottom) + 127)/255,
(GetGValue(rgbTop)*alpha + k*GetGValue(rgbBottom) + 127)/255,
(GetBValue(rgbTop)*alpha + k*GetBValue(rgbBottom) + 127)/255);
}
INT
Graphics_GetColorDistance(COLORREF rgb1, COLORREF rgb2)
{
return (1000 * ((GetRValue(rgb1) - GetRValue(rgb2)) +
(GetGValue(rgb1) - GetGValue(rgb2)) +
(GetBValue(rgb1) - GetBValue(rgb2))))/ (3 * 255);
}
void
Graphics_ClampRect(RECT *rect, const RECT *boxRect)
{
if (rect->left < boxRect->left)
rect->left = boxRect->left;
if (rect->top < boxRect->top)
rect->top = boxRect->top;
if (rect->right > boxRect->right)
rect->right = boxRect->right;
if (rect->bottom > boxRect->bottom)
rect->bottom = boxRect->bottom;
}
void
Graphics_NormalizeRect(RECT *rect)
{
if (rect->top > rect->bottom)
rect->bottom = rect->top;
if (rect->left > rect->right)
rect->right = rect->left;
}
void
Graphics_GetRectSizeNormalized(const RECT *rect, SIZE *size)
{
size->cx = rect->right - rect->left;
if (size->cx < 0)
size->cx = 0;
size->cy = rect->bottom - rect->top;
if (size->cy < 0)
size->cy = 0;
}
BOOL
Graphics_IsRectFit(const RECT *rect, const RECT *boxRect)
{
if (rect->left < boxRect->left ||
rect->top < boxRect->top ||
rect->right > boxRect->right ||
rect->bottom > boxRect->bottom)
{
return FALSE;
}
return TRUE;
}
BOOL SetSizeEmpty(SIZE *size)
{
if (NULL == size)
return FALSE;
ZeroMemory(size, sizeof(SIZE));
return TRUE;
}
BOOL IsSizeEmpty(SIZE *size)
{
return (NULL == size || 0 == size->cx || 0 == size->cy);
}
BOOL SetSize(SIZE *size, long width, long height)
{
if (NULL == size)
return FALSE;
size->cx = width;
size->cy = height;
return TRUE;
}
BOOL SetPoint(POINT *pt, long x, long y)
{
if (NULL == pt)
return FALSE;
pt->x = x;
pt->y = y;
return TRUE;
}
BOOL MakeRectPolygon(POINT vertices[4], long left, long top, long right, long bottom)
{
if (NULL == vertices)
return FALSE;
vertices[0].x = left;
vertices[0].y = top;
vertices[1].x = right;
vertices[1].y = top;
vertices[2].x = right;
vertices[2].y = bottom;
vertices[3].x = left;
vertices[3].y = bottom;
return TRUE;
}
+72
View File
@@ -0,0 +1,72 @@
#ifndef _NULLSOFT_WINAMP_ML_DEVICES_GRAPHICS_HEADER
#define _NULLSOFT_WINAMP_ML_DEVICES_GRAPHICS_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#ifndef SelectBitmap
#define SelectBitmap(_hdc, _bitmap) ((HBITMAP)SelectObject(_hdc, _bitmap))
#endif
#ifndef SelectFont
#define SelectFont(_hdc, _font) ((HFONT)SelectObject(_hdc, _font))
#endif
#ifndef SelectBrush
#define SelectBrush(_hdc, _brush) ((HBRUSH)SelectObject(_hdc, _brush))
#endif
#ifndef GetCurrentBitmap
#define GetCurrentBitmap(_hdc) ((HBITMAP)GetCurrentObject(_hdc, OBJ_BITMAP))
#endif
#ifndef GetCurrentFont
#define GetCurrentFont(_hdc) ((HFONT)GetCurrentObject(_hdc, OBJ_FONT))
#endif
#ifndef GetCurrentBrush
#define GetCurrentBrush(_hdc) ((HBRUSH)GetCurrentObject(_hdc, OBJ_BRUSH))
#endif
#ifndef SET_GRADIENT_VERTEX
#define SET_GRADIENT_VERTEX(_vertex, _x, _y, _rgb)\
{(_vertex).x = (_x); (_vertex).y = (_y);\
(_vertex).Red = GetRValue(_rgb) << 8; (_vertex).Green = GetGValue(_rgb) << 8;\
(_vertex).Blue = GetBValue(_rgb) << 8; (_vertex).Alpha = 0x0000;}
#endif
#ifndef SET_GRADIENT_RECT_MESH
#define SET_GRADIENT_RECT_MESH(_mesh, _upperLeft, _bottomRight)\
{(_mesh).UpperLeft = (_upperLeft); (_mesh).LowerRight = (_bottomRight);}
#endif
BYTE Graphics_GetSysFontQuality();
HFONT Graphics_CreateSysFont();
HFONT Graphics_DuplicateFont(HFONT sourceFont, INT heightDeltaPt, BOOL forceBold, BOOL systemQuality);
long Graphics_GetFontHeight(HDC hdc);
long Graphics_GetAveStrWidth(HDC hdc, UINT cchLen);
BOOL Graphics_GetWindowBaseUnits(HWND hwnd, LONG *baseUnitX, LONG *baseUnitY);
COLORREF Graphics_GetSkinColor(unsigned int colorIndex);
COLORREF Graphics_BlendColors(COLORREF rgbTop, COLORREF rgbBottom, INT alpha);
INT Graphics_GetColorDistance(COLORREF rgb1, COLORREF rgb2);
void Graphics_ClampRect(RECT *rect, const RECT *boxRect);
void Graphics_NormalizeRect(RECT *rect);
void Graphics_GetRectSizeNormalized(const RECT *rect, SIZE *size);
BOOL Graphics_IsRectFit(const RECT *rect, const RECT *boxRect);
BOOL SetSizeEmpty(SIZE *size);
BOOL IsSizeEmpty(SIZE *size);
BOOL SetSize(SIZE *size, long width, long height);
BOOL SetPoint(POINT *pt, long x, long y);
BOOL MakeRectPolygon(POINT vertices[4], long left, long top, long right, long bottom);
#endif //_NULLSOFT_WINAMP_ML_DEVICES_GRAPHICS_HEADER
+978
View File
@@ -0,0 +1,978 @@
#include "main.h"
#include "./image.h"
HBITMAP
Image_Load(const wchar_t *path, unsigned int type,
unsigned int flags, int width, int height)
{
MLIMAGESOURCE source;
HWND libraryWindow = Plugin_GetLibraryWindow();
if (NULL == libraryWindow)
return NULL;
source.cbSize = sizeof(source);
source.lpszName = path;
source.type = type;
source.flags = (flags & ~IMAGE_FILTER_MASK);
source.cxDst = width;
source.cyDst = height;
if (0 == (ISF_LOADFROMFILE & source.flags))
{
source.hInst = WASABI_API_LNG_HINST;
if (NULL != source.hInst)
{
HBITMAP bitmap = MLImageLoader_LoadDib(libraryWindow, &source);
if (NULL != bitmap)
return bitmap;
}
if (WASABI_API_ORIG_HINST == source.hInst)
return NULL;
source.hInst = WASABI_API_ORIG_HINST;
return (NULL != source.hInst) ?
MLImageLoader_LoadDib(libraryWindow, &source) :
NULL;
}
return MLImageLoader_LoadDib(Plugin_GetLibraryWindow(), &source);
}
HBITMAP
Image_LoadEx(HINSTANCE instance, const wchar_t *path, unsigned int type,
unsigned int flags, int width, int height)
{
MLIMAGESOURCE source = {0};
source.cbSize = sizeof(source);
source.hInst = instance;
source.lpszName = path;
source.type = type;
source.flags = (flags & ~IMAGE_FILTER_MASK);
source.cxDst = width;
source.cyDst = height;
return MLImageLoader_LoadDib(Plugin_GetLibraryWindow(), &source);
}
BOOL
Image_FilterEx(void *pixelData, long width, long height, unsigned short bpp,
unsigned int flags, COLORREF backColor, COLORREF frontColor, COLORREF blendColor)
{
MLIMAGEFILTERAPPLYEX filter;
HWND libraryWindow;
BOOL result;
if (NULL == pixelData)
return FALSE;
libraryWindow = Plugin_GetLibraryWindow();
if (NULL == libraryWindow)
return FALSE;
filter.cbSize = sizeof(filter);
filter.pData = (BYTE*)pixelData;
filter.cx = width;
filter.cy = height;
filter.bpp = bpp;
filter.imageTag = NULL;
result = FALSE;
if (0 != (IMAGE_FILTER_GRAYSCALE & flags))
{
filter.filterUID = MLIF_GRAYSCALE_UID;
result = MLImageFilter_ApplyEx(libraryWindow, &filter);
}
filter.rgbBk = backColor;
filter.rgbFg = frontColor;
if (32 == bpp)
{
filter.filterUID = MLIF_FILTER1_PRESERVE_ALPHA_UID;
result = MLImageFilter_ApplyEx(libraryWindow, &filter);
if (0 != (IMAGE_FILTER_BLEND & flags))
{
filter.filterUID = MLIF_BLENDONBK_UID;
filter.rgbBk = blendColor;
result = MLImageFilter_ApplyEx(libraryWindow, &filter);
}
}
else
{
filter.filterUID = MLIF_FILTER1_UID;
result = MLImageFilter_ApplyEx(libraryWindow, &filter);
}
return result;
}
BOOL
Image_Filter(HBITMAP bitmap, unsigned int flags,
COLORREF backColor, COLORREF frontColor, COLORREF blendColor)
{
DIBSECTION bitmapData;
BITMAP *bi;
if (NULL == bitmap)
return NULL;
if (sizeof(bitmapData) != GetObjectW(bitmap, sizeof(bitmapData), &bitmapData))
return FALSE;
bi = &bitmapData.dsBm;
return Image_FilterEx(bi->bmBits, bi->bmWidth, bi->bmHeight, bi->bmBitsPixel,
flags, backColor, frontColor, blendColor);
}
BOOL
Image_BlendEx(void *pixelData, long width, long height, unsigned short bpp, COLORREF blendColor)
{
MLIMAGEFILTERAPPLYEX filter;
HWND libraryWindow;
if (NULL == pixelData || 32 != bpp)
return FALSE;
libraryWindow = Plugin_GetLibraryWindow();
if (NULL == libraryWindow)
return FALSE;
filter.cbSize = sizeof(filter);
filter.pData = (BYTE*)pixelData;
filter.cx = width;
filter.cy = height;
filter.bpp = bpp;
filter.imageTag = NULL;
filter.filterUID = MLIF_BLENDONBK_UID;
filter.rgbBk = blendColor;
return MLImageFilter_ApplyEx(libraryWindow, &filter);
}
BOOL
Image_Blend(HBITMAP bitmap, COLORREF blendColor)
{
DIBSECTION bitmapData;
BITMAP *bi;
if (NULL == bitmap)
return NULL;
if (sizeof(bitmapData) != GetObjectW(bitmap, sizeof(bitmapData), &bitmapData))
return FALSE;
bi = &bitmapData.dsBm;
return Image_BlendEx(bi->bmBits, bi->bmWidth, bi->bmHeight, bi->bmBitsPixel, blendColor);
}
HBITMAP
Image_LoadSkinnedEx(HINSTANCE instance, const wchar_t *path, unsigned int type,
unsigned int flags, int width, int height,
COLORREF backColor, COLORREF frontColor, COLORREF blendColor)
{
HBITMAP bitmap;
bitmap = Image_LoadEx(instance, path, type, flags, width, height);
if (NULL == bitmap)
return NULL;
Image_Filter(bitmap, flags, backColor, frontColor, blendColor);
return bitmap;
}
HBITMAP
Image_LoadSkinned(const wchar_t *path, unsigned int type,
unsigned int flags, int width, int height,
COLORREF backColor, COLORREF frontColor, COLORREF blendColor)
{
HBITMAP bitmap;
bitmap = Image_Load(path, type, flags, width, height);
if (NULL == bitmap)
return NULL;
Image_Filter(bitmap, flags, backColor, frontColor, blendColor);
return bitmap;
}
HBITMAP
Image_DuplicateDib(HBITMAP source)
{
HBITMAP bitmap;
DIBSECTION sourceDib;
HDC windowDC;
void *pixelData;
if (NULL == source)
return NULL;
if (sizeof(sourceDib) != GetObjectW(source, sizeof(sourceDib), &sourceDib))
return FALSE;
sourceDib.dsBmih.biSize = sizeof(BITMAPINFOHEADER);
if (sourceDib.dsBmih.biHeight > 0)
sourceDib.dsBmih.biHeight = -sourceDib.dsBmih.biHeight;
windowDC = GetDCEx(NULL, NULL, DCX_WINDOW | DCX_CACHE);
bitmap = CreateDIBSection(windowDC, (BITMAPINFO*)&sourceDib.dsBmih, DIB_RGB_COLORS, &pixelData, NULL, 0);
if (NULL != windowDC)
ReleaseDC(NULL, windowDC);
if (NULL == bitmap)
return NULL;
CopyMemory(pixelData, sourceDib.dsBm.bmBits, sourceDib.dsBm.bmWidthBytes * sourceDib.dsBm.bmHeight);
return bitmap;
}
BOOL
Image_ColorOver(HBITMAP bitmap, const RECT *prcPart, BOOL premult, COLORREF rgb)
{
DIBSECTION bitmapData;
BITMAP *bi;
if (NULL == bitmap)
return NULL;
if (sizeof(bitmapData) != GetObjectW(bitmap, sizeof(bitmapData), &bitmapData))
return FALSE;
if (BI_RGB != bitmapData.dsBmih.biCompression ||
1 != bitmapData.dsBmih.biPlanes ||
32 != bitmapData.dsBm.bmBitsPixel)
{
return FALSE;
}
bi = &bitmapData.dsBm;
return (NULL == prcPart) ?
Image_ColorOverEx((BYTE*)bi->bmBits, bi->bmWidth, bi->bmHeight,
0, 0, bi->bmWidth, bi->bmHeight,
bi->bmBitsPixel, premult, rgb) :
Image_ColorOverEx((BYTE*)bi->bmBits, bi->bmWidth, bi->bmHeight,
prcPart->left, prcPart->top,
prcPart->right - prcPart->left, prcPart->bottom - prcPart->top,
bi->bmBitsPixel, premult, rgb);
}
BOOL
Image_ColorOverEx(unsigned char *pPixels, int bitmapCX, int bitmapCY,
long x, long y, long cx, long cy, unsigned short bpp,
BOOL premult, COLORREF rgb)
{
LONG pitch;
UINT a, r, g, b, ma, mr, mg, mb;
INT step = (bpp>>3);
LPBYTE line, cursor;
pitch = bitmapCX * step;
while (pitch%4) pitch++;
if (step < 3)
return TRUE;
if (cy < 0) cy -= cy;
a = (LOBYTE((rgb)>>24)); r = GetRValue(rgb); g = GetGValue(rgb); b = GetBValue(rgb);
ma = 255 - a; mr = r * 255; mg = g * 255; mb = b * 255;
if (0 == a)
return TRUE;
INT ofs = (bitmapCY > 0) ? (bitmapCY - (y + cy)) : y;
line = pPixels + pitch * ofs + x*step;
if (0xFF == a)
{
for (; cy-- != 0; line += pitch)
{
for (x = cx, cursor = line; x-- != 0; cursor += step)
{
cursor[0] = (BYTE)b;
cursor[1] = (BYTE)g;
cursor[2] = (BYTE)r;
// cursor[3] = 0xFF;
}
}
return TRUE;
}
if (premult)
{
for (; cy-- != 0; line += pitch)
{
for (x = cx, cursor = line; x-- != 0; cursor += step)
{
int t = (mb + ma * cursor[0] + 127) / 255;
cursor[0] = (t > 0xFF) ? 0xFF : t;
t = (mg + ma * cursor[1] + 127) / 255;
cursor[1] = (t > 0xFF) ? 0xFF : t;
t = (mr+ ma * cursor[2] + 127) / 255;
cursor[2] = (t > 0xFF) ? 0xFF : t;
}
}
}
else
{
WORD k = (((255 - a)*255 + 127)/255);
for (; cy-- != 0; line += pitch)
{
for (x = cx, cursor = line; x-- != 0; cursor += step)
{
cursor[0] = (b*a + k*cursor[0] + 127)/255;
cursor[1] = (g*a + k*cursor[1] + 127)/255;
cursor[2] = (r*a + k*cursor[2] + 127)/255;
// cursor[3] = (a*a + k*cursor[3] + 127)/255;
}
}
}
return TRUE;
}
BOOL
Image_Premultiply(HBITMAP hbmp, const RECT *prcPart)
{
DIBSECTION dibsec;
if (!hbmp || sizeof(DIBSECTION) != GetObject(hbmp, sizeof(DIBSECTION), &dibsec) ||
BI_RGB != dibsec.dsBmih.biCompression || 1 != dibsec.dsBmih.biPlanes || dibsec.dsBm.bmBitsPixel != 32)
return FALSE;
return (NULL == prcPart) ?
Image_PremultiplyEx((BYTE*)dibsec.dsBm.bmBits, dibsec.dsBm.bmWidth, dibsec.dsBm.bmHeight,
0, 0, dibsec.dsBm.bmWidth, dibsec.dsBm.bmHeight,
dibsec.dsBm.bmBitsPixel) :
Image_PremultiplyEx((BYTE*)dibsec.dsBm.bmBits, dibsec.dsBm.bmWidth, dibsec.dsBm.bmHeight,
prcPart->left, prcPart->top, RECTWIDTH(*prcPart), RECTHEIGHT(*prcPart),
dibsec.dsBm.bmBitsPixel);
}
BOOL
Image_PremultiplyEx(unsigned char *pPixels, int bitmapCX, int bitmapCY,
long x, long y, long cx, long cy, unsigned short bpp)
{
if (32 != bpp)
return FALSE;
LONG pitch;
INT step = (bpp>>3);
LPBYTE line, cursor;
pitch = bitmapCX * step;
while (pitch%4) pitch++;
if (cy < 0)
cy = -cy;
INT ofs = (bitmapCY > 0) ? (bitmapCY - (y + cy)) : y;
line = pPixels + pitch * ofs + x*step;
UINT a;
for (; cy-- != 0; line += pitch)
{
for (x = cx, cursor = line; x-- != 0; cursor += step)
{
a = cursor[3];
if (0 == a)
{
cursor[0] = 0;
cursor[1] = 0;
cursor[2] = 0;
}
else if (255 != a)
{
cursor[0] = (BYTE)MulDiv(cursor[0], a, 255);
cursor[1] = (BYTE)MulDiv(cursor[1], a, 255);
cursor[2] = (BYTE)MulDiv(cursor[2], a, 255);
}
}
}
return TRUE;
}
BOOL
Image_Demultiply(HBITMAP hbmp, const RECT *prcPart)
{
DIBSECTION dibsec;
if (!hbmp || sizeof(DIBSECTION) != GetObject(hbmp, sizeof(DIBSECTION), &dibsec) ||
BI_RGB != dibsec.dsBmih.biCompression || 1 != dibsec.dsBmih.biPlanes || dibsec.dsBm.bmBitsPixel != 32)
return FALSE;
return (NULL == prcPart) ?
Image_DemultiplyEx((BYTE*)dibsec.dsBm.bmBits, dibsec.dsBm.bmWidth, dibsec.dsBm.bmHeight,
0, 0, dibsec.dsBm.bmWidth, dibsec.dsBm.bmHeight,
dibsec.dsBm.bmBitsPixel) :
Image_DemultiplyEx((BYTE*)dibsec.dsBm.bmBits, dibsec.dsBm.bmWidth, dibsec.dsBm.bmHeight,
prcPart->left, prcPart->top, RECTWIDTH(*prcPart), RECTHEIGHT(*prcPart),
dibsec.dsBm.bmBitsPixel);
}
BOOL
Image_DemultiplyEx(unsigned char *pPixels, int bitmapCX, int bitmapCY,
long x, long y, long cx, long cy, unsigned short bpp)
{
if (32 != bpp)
return FALSE;
LONG pitch;
INT step = (bpp>>3);
LPBYTE line, cursor;
pitch = bitmapCX * step;
while (pitch%4) pitch++;
if (cy < 0)
cy = -cy;
INT ofs = (bitmapCY > 0) ? (bitmapCY - (y + cy)) : y;
line = pPixels + pitch * ofs + x*step;
UINT a;
for (; cy-- != 0; line += pitch)
{
for (x = cx, cursor = line; x-- != 0; cursor += step)
{
a = cursor[3];
if (0 == a)
{
cursor[0] = 0;
cursor[1] = 0;
cursor[2] = 0;
}
else if (255 != a)
{
cursor[0] = (BYTE)MulDiv(cursor[0], 255, a);
cursor[1] = (BYTE)MulDiv(cursor[1], 255, a);
cursor[2] = (BYTE)MulDiv(cursor[2], 255, a);
}
}
}
return TRUE;
}
BOOL
Image_Saturate(HBITMAP hbmp, const RECT *prcPart, int n, BOOL fScale)
{
DIBSECTION dibsec;
if (!hbmp || sizeof(DIBSECTION) != GetObject(hbmp, sizeof(DIBSECTION), &dibsec) ||
BI_RGB != dibsec.dsBmih.biCompression || 1 != dibsec.dsBmih.biPlanes || dibsec.dsBm.bmBitsPixel != 32)
return FALSE;
return Image_SaturateEx((BYTE*)dibsec.dsBm.bmBits, dibsec.dsBm.bmWidth, dibsec.dsBm.bmHeight,
prcPart->left, prcPart->top,
prcPart->right - prcPart->left, prcPart->bottom - prcPart->top,
dibsec.dsBm.bmBitsPixel, n, fScale);
}
BOOL
Image_SaturateEx(unsigned char *pPixels, int bitmapCX, int bitmapCY,
long x, long y, long cx, long cy, unsigned short bpp,
int n, BOOL fScale)
{
if (32 != bpp)
return FALSE;
LONG pitch;
INT step = (bpp>>3);
LPBYTE line, cursor;
pitch = bitmapCX * step;
while (pitch%4) pitch++;
if (FALSE == fScale)
{
if (n < 0) n = 0;
else if (n > 1000) n = 1000;
}
else
{
if (n < -1000) n = -1000;
else if (n > 1000) n = 1000;
}
if (cy < 0)
cy = -cy;
INT ofs = (bitmapCY > 0) ? (bitmapCY - (y + cy)) : y;
line = pPixels + pitch * ofs + x*step;
COLORREF rgb;
INT k;
WORD h, l, s;
for (; cy-- != 0; line += pitch)
{
for (x = cx, cursor = line; x-- != 0; cursor += step)
{
rgb = RGB(cursor[2], cursor[1], cursor[0]);
ColorRGBToHLS(rgb, &h, &l, &s);
if(FALSE == fScale)
s = ((WORD)((240 * n)/1000));
else
{
k = s;
s = (WORD)(k + (k * n) /1000);
}
rgb = ColorHLSToRGB(h, l, s);
cursor[0] = GetBValue(rgb);
cursor[1] = GetGValue(rgb);
cursor[2] = GetRValue(rgb);
}
}
return TRUE;
}
BOOL
Image_AdjustAlpha(HBITMAP hbmp, const RECT *prcPart, int n, BOOL fScale)
{
DIBSECTION dibsec;
if (!hbmp || sizeof(DIBSECTION) != GetObject(hbmp, sizeof(DIBSECTION), &dibsec) ||
BI_RGB != dibsec.dsBmih.biCompression || 1 != dibsec.dsBmih.biPlanes || dibsec.dsBm.bmBitsPixel != 32)
return FALSE;
return Image_AdjustAlphaEx((BYTE*)dibsec.dsBm.bmBits, dibsec.dsBm.bmWidth, dibsec.dsBm.bmHeight,
prcPart->left, prcPart->top,
prcPart->right - prcPart->left, prcPart->bottom - prcPart->top,
dibsec.dsBm.bmBitsPixel, n, fScale);
}
BOOL
Image_AdjustAlphaEx(unsigned char *pPixels, int bitmapCX, int bitmapCY,
long x, long y, long cx, long cy, unsigned short bpp,
int n, BOOL fScale)
{
if (32 != bpp)
return FALSE;
LONG pitch;
INT step = (bpp>>3);
LPBYTE line, cursor;
pitch = bitmapCX * step;
while (pitch%4) pitch++;
if (FALSE == fScale)
{
if (n < 0) n = 0;
else if (n > 1000) n = 1000;
}
else
{
if (n < -1000) n = -1000;
else if (n > 1000) n = 1000;
}
if (cy < 0)
cy = -cy;
INT ofs = (bitmapCY > 0) ? (bitmapCY - (y + cy)) : y;
line = pPixels + pitch * ofs + x*step;
INT k;
for (; cy-- != 0; line += pitch)
{
for (x = cx, cursor = line; x-- != 0; cursor += step)
{
if(FALSE == fScale)
cursor[3] = ((BYTE)((255 * n)/1000));
else
{
k = cursor[3];
k = k + MulDiv(k, n, 1000);
if (k > 255) k = 255;
cursor[3] = (BYTE)k;
}
}
}
return TRUE;
}
BOOL
Image_AdjustSaturationAlpha(HBITMAP hbmp, const RECT *prcPart, int nSaturation, int nAlpha)
{
DIBSECTION dibsec;
if (!hbmp || sizeof(DIBSECTION) != GetObject(hbmp, sizeof(DIBSECTION), &dibsec) ||
BI_RGB != dibsec.dsBmih.biCompression || 1 != dibsec.dsBmih.biPlanes || dibsec.dsBm.bmBitsPixel != 32)
return FALSE;
return Image_AdjustSaturationAlphaEx((BYTE*)dibsec.dsBm.bmBits, dibsec.dsBm.bmWidth, dibsec.dsBm.bmHeight,
prcPart->left, prcPart->top,
prcPart->right - prcPart->left, prcPart->bottom - prcPart->top,
dibsec.dsBm.bmBitsPixel, nSaturation, nAlpha);
}
BOOL
Image_AdjustSaturationAlphaEx(unsigned char *pPixels, int bitmapCX, int bitmapCY,
long x, long y, long cx, long cy,
unsigned short bpp, int nSaturation, int nAlpha)
{
if (32 != bpp)
return FALSE;
LONG pitch;
INT step = (bpp>>3);
LPBYTE line, cursor;
pitch = bitmapCX * step;
while (pitch%4) pitch++;
if (nSaturation < -1000) nSaturation = -1000;
else if (nSaturation > 1000) nSaturation = 1000;
if (nAlpha < -1000) nAlpha = -1000;
else if (nAlpha > 1000) nAlpha = 1000;
if (cy < 0)
cy = -cy;
INT ofs = (bitmapCY > 0) ? (bitmapCY - (y + cy)) : y;
line = pPixels + pitch * ofs + x*step;
INT k;
COLORREF rgb;
WORD h, l, s;
for (; cy-- != 0; line += pitch)
{
for (x = cx, cursor = line; x-- != 0; cursor += step)
{
k = cursor[3];
k = k + MulDiv(k, nAlpha, 1000);
if (k > 255) k = 255;
cursor[3] = (BYTE)k;
rgb = RGB(cursor[2], cursor[1], cursor[0]);
ColorRGBToHLS(rgb, &h, &l, &s);
k = s;
k = k + MulDiv(k, nSaturation, 1000);
if (k > 240) k = 240;
s = (WORD)k;
rgb = ColorHLSToRGB(h, l, s);
cursor[0] = GetBValue(rgb);
cursor[1] = GetGValue(rgb);
cursor[2] = GetRValue(rgb);
}
}
return TRUE;
}
BOOL
Image_FillBorder(HDC targetDC, const RECT *targetRect,
HDC sourceDC, const RECT *sourceRect,
BOOL fillCenter, BYTE alphaConstant)
{
INT prevStretchMode;
long centerWidth, centerHeight;
long sliceWidth, sliceHeight;
const BLENDFUNCTION blendFunction = { AC_SRC_OVER, 0, alphaConstant, AC_SRC_ALPHA };
const long targetWidth = RECTWIDTH(*targetRect);
const long targetHeight = RECTHEIGHT(*targetRect);
const long sourceWidth = RECTWIDTH(*sourceRect);
const long sourceHeight = RECTHEIGHT(*sourceRect);
if (NULL == targetDC || NULL == sourceDC)
return FALSE;
sliceWidth = sourceWidth/2;
sliceHeight = sourceHeight/2;
if (sliceWidth*2 > targetWidth)
sliceWidth = targetWidth/2;
if (sliceHeight*2 > targetHeight)
sliceHeight = targetHeight/2;
if (0 == sliceWidth || 0 == sliceHeight)
return FALSE;
prevStretchMode = SetStretchBltMode(targetDC, COLORONCOLOR);
SetViewportOrgEx(sourceDC, 0, 0, NULL);
GdiAlphaBlend(targetDC, targetRect->left, targetRect->top, sliceWidth, sliceHeight,
sourceDC, sourceRect->left, sourceRect->top, sliceWidth, sliceHeight, blendFunction);
GdiAlphaBlend(targetDC, targetRect->right - sliceWidth, targetRect->top, sliceWidth, sliceHeight,
sourceDC, sourceRect->right - sliceWidth, sourceRect->top, sliceWidth, sliceHeight, blendFunction);
GdiAlphaBlend(targetDC, targetRect->left, targetRect->bottom - sliceHeight, sliceWidth, sliceHeight,
sourceDC, sourceRect->left, sourceRect->bottom - sliceHeight, sliceWidth, sliceHeight, blendFunction);
GdiAlphaBlend(targetDC, targetRect->right - sliceWidth, targetRect->bottom - sliceHeight, sliceWidth, sliceHeight,
sourceDC, sourceRect->right - sliceWidth, sourceRect->bottom - sliceHeight, sliceWidth, sliceHeight, blendFunction);
if (targetWidth > 2*sliceWidth)
{
centerWidth = sourceWidth - 2*sliceWidth;
if(centerWidth < 1)
centerWidth = 1;
GdiAlphaBlend(targetDC, targetRect->left + sliceWidth, targetRect->top, targetWidth - (sliceWidth * 2), sliceHeight,
sourceDC, sourceRect->left + sliceWidth, sourceRect->top, centerWidth, sliceHeight, blendFunction);
GdiAlphaBlend(targetDC, targetRect->left + sliceWidth, targetRect->bottom - sliceHeight, targetWidth - (sliceWidth * 2), sliceHeight,
sourceDC, sourceRect->left + sliceWidth, sourceRect->bottom - sliceHeight, centerWidth, sliceHeight, blendFunction);
}
else
centerWidth = 0;
if (targetHeight > 2*sliceHeight)
{
centerHeight = sourceHeight - 2*sliceHeight;
if(centerHeight < 1)
centerHeight = 1;
GdiAlphaBlend(targetDC, targetRect->left, targetRect->top + sliceHeight, sliceWidth, targetHeight - (sliceHeight* 2),
sourceDC, sourceRect->left, sourceRect->top + sliceHeight, sliceWidth, centerHeight, blendFunction);
GdiAlphaBlend(targetDC, targetRect->right - sliceWidth, targetRect->top + sliceHeight, sliceWidth, targetHeight - (sliceHeight* 2),
sourceDC, sourceRect->right - sliceWidth, sourceRect->top + sliceHeight, sliceWidth, centerHeight, blendFunction);
}
else
centerHeight = 0;
if (FALSE != fillCenter &&
0 != centerWidth && 0 != centerHeight)
{
GdiAlphaBlend(targetDC, targetRect->left + sliceWidth, targetRect->top + sliceHeight, targetWidth - (sliceWidth * 2), targetHeight - (sliceHeight* 2),
sourceDC, sourceRect->left + sliceWidth, sourceRect->top + sliceHeight, centerWidth, centerHeight, blendFunction);
}
SetStretchBltMode(targetDC, prevStretchMode);
return TRUE;
}
const ImageInfo *
Image_GetBestFit(const ImageInfo *images, size_t count, unsigned int width, unsigned int height)
{
const ImageInfo *image, *bestFit;
double widthDbl, heightDbl;
double scaleMin, scaleHorz, scaleVert;
if (NULL == images || count < 1)
return NULL;
if (width < 1)
width = 1;
if (height < 1)
height = 1;
widthDbl = width;
heightDbl = height;
image = &images[--count];
scaleHorz = widthDbl/image->width;
scaleVert = heightDbl/image->height;
scaleMin = (scaleHorz < scaleVert) ? scaleHorz : scaleVert;
bestFit = image;
if (1.0 != scaleMin)
{
scaleMin = fabs(1.0 - scaleMin);
while(count--)
{
image = &images[count];
scaleHorz = widthDbl/image->width;
scaleVert = heightDbl/image->height;
if (scaleHorz > scaleVert)
scaleHorz = scaleVert;
if (1.0 == scaleHorz)
{
bestFit = image;
break;
}
scaleHorz = fabs(1.0 - scaleHorz);
if (scaleHorz < scaleMin)
{
scaleMin = scaleHorz;
bestFit = image;
}
}
}
return bestFit;
}
BOOL
Image_AlphaBlend(HDC targetDC, const RECT *targetRect,
HDC sourceDC, const RECT *sourceRect, BYTE sourceAlpha,
HBITMAP sourceBitmap, const RECT *paintRect, AlphaBlendFlags flags,
RECT *rectOut)
{
BOOL result, clipSource;
RECT fillRect;
int sourceX, sourceY, sourceWidth, sourceHeight;
const BLENDFUNCTION blendFunction =
{
AC_SRC_OVER,
0,
sourceAlpha,
AC_SRC_ALPHA
};
if (NULL != paintRect)
{
if (FALSE == IntersectRect(&fillRect, targetRect, paintRect))
return TRUE;
clipSource = TRUE;
}
else
{
CopyRect(&fillRect, targetRect);
clipSource = FALSE;
}
if (NULL != sourceRect)
{
sourceX = sourceRect->left;
sourceY = sourceRect->top;
sourceWidth = RECTWIDTH(*sourceRect);
sourceHeight = RECTHEIGHT(*sourceRect);
}
else
{
BITMAP bitmapInfo;
if (sizeof(bitmapInfo) != GetObject(sourceBitmap, sizeof(bitmapInfo), &bitmapInfo))
return FALSE;
sourceX = 0;
sourceY = 0;
sourceWidth = bitmapInfo.bmWidth;
sourceHeight = bitmapInfo.bmHeight;
if (sourceHeight < 0)
sourceHeight = -sourceHeight;
}
if (0 != (AlphaBlend_ScaleSource & flags))
{
RECT rect;
double scaleHorz, scaleVert;
scaleHorz = (double)RECTWIDTH(*targetRect) / sourceWidth;
scaleVert = (double)RECTHEIGHT(*targetRect) / sourceHeight;
if (scaleHorz > scaleVert)
scaleHorz = scaleVert;
SetRect(&rect, 0, 0, (int)(sourceWidth * scaleHorz), (int)(sourceHeight * scaleHorz));
if (0 != (AlphaBlend_AlignLeft & flags))
rect.left = targetRect->left;
else if (0 != (AlphaBlend_AlignRight & flags))
rect.left = targetRect->right - rect.right;
else
rect.left = targetRect->left + (RECTWIDTH(*targetRect) - rect.right)/2;
if (0 != (AlphaBlend_AlignTop & flags))
rect.top = targetRect->top;
else if (0 != (AlphaBlend_AlignBottom & flags))
rect.top = targetRect->bottom - rect.bottom;
else
rect.top = targetRect->top + (RECTHEIGHT(*targetRect) - rect.bottom)/2;
rect.right += rect.left;
rect.bottom += rect.top;
if (NULL != rectOut)
CopyRect(rectOut, &rect);
if (NULL != paintRect)
{
if (FALSE == IntersectRect(&fillRect, &rect, paintRect))
return TRUE;
}
else
CopyRect(&fillRect, &rect);
sourceX += (int)((fillRect.left - rect.left)/scaleHorz);
sourceY += (int)((fillRect.top - rect.top)/ scaleHorz);
sourceWidth -= (int)((RECTWIDTH(rect) - RECTWIDTH(fillRect))/scaleHorz);
sourceHeight -= (int)((RECTHEIGHT(rect) - RECTHEIGHT(fillRect))/scaleHorz);
clipSource = FALSE;
}
else
{
if (sourceWidth < RECTWIDTH(*targetRect) ||
sourceHeight < RECTHEIGHT(*targetRect))
{
RECT rect;
if (0 != (AlphaBlend_AlignLeft & flags))
rect.left = targetRect->left;
else if (0 != (AlphaBlend_AlignRight & flags))
rect.left = targetRect->right - sourceWidth;
else
rect.left = targetRect->left + (RECTWIDTH(*targetRect) - sourceWidth)/2;
if (0 != (AlphaBlend_AlignTop & flags))
rect.top = targetRect->top;
else if (0 != (AlphaBlend_AlignBottom & flags))
rect.top = targetRect->bottom - sourceHeight;
else
rect.top = targetRect->top + (RECTHEIGHT(*targetRect) - sourceHeight)/2;
rect.right = rect.left + sourceWidth;
rect.bottom = rect.top + sourceHeight;
if (NULL != paintRect)
{
if (FALSE == IntersectRect(&fillRect, &rect, paintRect))
return TRUE;
sourceX += (fillRect.left - rect.left);
sourceY += (fillRect.top - rect.top);
sourceWidth -= (RECTWIDTH(rect) - RECTWIDTH(fillRect));
sourceHeight -= (RECTHEIGHT(rect) - RECTHEIGHT(fillRect));
}
else
CopyRect(&fillRect, &rect);
if (NULL != rectOut)
CopyRect(rectOut, &rect);
clipSource = FALSE;
}
else if (NULL != rectOut)
CopyRect(rectOut, targetRect);
}
if (FALSE != clipSource)
{
sourceX += (fillRect.left - targetRect->left);
sourceY += (fillRect.top - targetRect->top);
sourceWidth -= (RECTWIDTH(*targetRect) - RECTWIDTH(fillRect));
sourceHeight -= (RECTHEIGHT(*targetRect) - RECTHEIGHT(fillRect));
}
if (NULL != sourceBitmap)
SelectBitmap(sourceDC, sourceBitmap);
result = GdiAlphaBlend(targetDC, fillRect.left, fillRect.top, RECTWIDTH(fillRect), RECTHEIGHT(fillRect),
sourceDC, sourceX, sourceY, sourceWidth, sourceHeight, blendFunction);
return result;
}
+227
View File
@@ -0,0 +1,227 @@
#ifndef _NULLSOFT_WINAMP_ML_DEVICES_IMAGE_HEADER
#define _NULLSOFT_WINAMP_ML_DEVICES_IMAGE_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#define IMAGE_FILTER_NORMAL 0x00000000
#define IMAGE_FILTER_GRAYSCALE 0x00010000
#define IMAGE_FILTER_BLEND 0x00020000
#define IMAGE_FILTER_MASK 0xFFFF0000
typedef struct ImageInfo
{
unsigned int width;
unsigned int height;
const wchar_t *path;
} ImageInfo;
HBITMAP
Image_Load(const wchar_t *path,
unsigned int type,
unsigned int flags,
int width,
int height);
HBITMAP
Image_LoadEx(HINSTANCE instance,
const wchar_t *path,
unsigned int type,
unsigned int flags,
int width,
int height);
HBITMAP
Image_LoadSkinned(const wchar_t *path,
unsigned int type,
unsigned int flags, //ISF_XXX + IMAGE_FILTER_XXX
int width,
int height,
COLORREF backColor,
COLORREF frontColor,
COLORREF blendColor); // only valid if IMAGE_FILTER_BLEND set
HBITMAP
Image_LoadSkinnedEx(HINSTANCE instance,
const wchar_t *path,
unsigned int type,
unsigned int flags, //ISF_XXX + IMAGE_FILTER_XXX
int width,
int height,
COLORREF backColor,
COLORREF frontColor,
COLORREF blendColor); // only valid if IMAGE_FILTER_BLEND set
BOOL
Image_FilterEx(void *pixelData,
long width,
long height,
unsigned short bpp,
unsigned int flags,
COLORREF backColor,
COLORREF frontColor,
COLORREF blendColor);
BOOL
Image_Filter(HBITMAP bitmap,
unsigned int flags,
COLORREF backColor,
COLORREF frontColor,
COLORREF blendColor);
BOOL
Image_BlendEx(void *pixelData,
long width,
long height,
unsigned short bpp,
COLORREF blendColor);
BOOL
Image_Blend(HBITMAP bitmap,
COLORREF blendColor);
HBITMAP
Image_DuplicateDib(HBITMAP source);
BOOL
Image_ColorOver(HBITMAP hbmp,
const RECT *prcPart,
BOOL premult,
COLORREF rgb);
BOOL
Image_ColorOverEx(unsigned char *pPixels,
int bitmapCX,
int bitmapCY,
long x,
long y,
long cx,
long cy,
unsigned short bpp,
BOOL premult,
COLORREF rgb);
BOOL
Image_Premultiply(HBITMAP hbmp,
const RECT *prcPart);
BOOL
Image_PremultiplyEx(unsigned char *pPixels,
int bitmapCX,
int bitmapCY,
long x,
long y,
long cx,
long cy,
unsigned short bpp);
BOOL
Image_Demultiply(HBITMAP hbmp,
const RECT *prcPart);
BOOL
Image_DemultiplyEx(unsigned char *pPixels,
int bitmapCX,
int bitmapCY,
long x,
long y,
long cx,
long cy,
unsigned short bpp);
BOOL
Image_Saturate(HBITMAP hbmp,
const RECT *prcPart,
int n,
BOOL fScale);
BOOL
Image_SaturateEx(unsigned char *pPixels,
int bitmapCX,
int bitmapCY,
long x,
long y,
long cx,
long cy,
unsigned short bpp,
int n,
BOOL fScale);
BOOL
Image_AdjustAlpha(HBITMAP hbmp,
const RECT *prcPart,
int n,
BOOL fScale);
BOOL
Image_AdjustAlphaEx(unsigned char *pPixels,
int bitmapCX,
int bitmapCY,
long x,
long y,
long cx,
long cy,
unsigned short bpp,
int n,
BOOL fScale);
BOOL
Image_AdjustSaturationAlpha(HBITMAP hbmp,
const RECT *prcPart,
int nSaturation,
int nAlpha);
BOOL
Image_AdjustSaturationAlphaEx(unsigned char *pPixels,
int bitmapCX,
int bitmapCY,
long x,
long y,
long cx,
long cy,
unsigned short bpp,
int nSaturation,
int nAlpha);
BOOL
Image_FillBorder(HDC targetDC,
const RECT *targetRect,
HDC sourceDC,
const RECT *sourceRect,
BOOL fillCenter,
BYTE alphaConstant);
const ImageInfo *
Image_GetBestFit(const ImageInfo *images,
size_t count,
unsigned int width,
unsigned int height);
typedef enum AlphaBlendFlags
{
AlphaBlend_Normal = 0,
AlphaBlend_ScaleSource = (1 << 0),
AlphaBlend_AlignLeft = (1 << 1),
AlphaBlend_AlignRight = (1 << 2),
AlphaBlend_AlignCenter = 0,
AlphaBlend_AlignTop = (1 << 3),
AlphaBlend_AlignBottom = (1 << 4),
AlphaBlend_AlignVCenter = 0,
}AlphaBlendFlags;
DEFINE_ENUM_FLAG_OPERATORS(AlphaBlendFlags);
BOOL
Image_AlphaBlend(HDC targetDC,
const RECT *targetRect,
HDC sourceDC,
const RECT *sourceRect,
BYTE sourceAlpha,
HBITMAP sourceBitmap,
const RECT *paintRect,
AlphaBlendFlags flags,
RECT *rectOut);
#endif //_NULLSOFT_WINAMP_ML_DEVICES_IMAGE_HEADER
@@ -0,0 +1,902 @@
#include "main.h"
#include "./imageCache.h"
#include <wincodec.h>
#include <vector>
#include <algorithm>
struct DeviceColoredImage
{
size_t ref;
DeviceImage *base;
HBITMAP bitmap;
COLORREF color1;
COLORREF color2;
DeviceImageFilter filter;
void *filterParam;
};
typedef std::vector<DeviceColoredImage*> DeviceColoredImageList;
struct DeviceImage
{
size_t ref;
DeviceImageCache *cache;
wchar_t *source;
HBITMAP bitmap;
HBITMAP exactBitmap;
int width;
int height;
DeviceImageLoader loader;
void *loaderParam;
DeviceColoredImageList list;
};
typedef std::vector<DeviceImage*> DeviceImageList;
struct DeviceImageCache
{
DeviceImageList list;
IWICImagingFactory *wicFactory;
};
typedef struct DeviceImageSeachParam
{
const wchar_t *path;
int width;
int height;
} DeviceImageSeachParam;
typedef struct DeviceColoredImageSeachParam
{
COLORREF color1;
COLORREF color2;
} DeviceColoredImageSeachParam;
DeviceImageCache *
DeviceImageCache_Create()
{
DeviceImageCache *self;
self = new DeviceImageCache();
if (NULL == self)
return NULL;
self->wicFactory = NULL;
return self;
}
void
DeviceImageCache_Free(DeviceImageCache *self)
{
if (NULL == self)
return;
size_t index = self->list.size();
while(index--)
{
DeviceImage *image = self->list[index];
image->cache = NULL;
}
if (NULL != self->wicFactory)
self->wicFactory->Release();
delete(self);
}
static DeviceImage *
DeviceImage_Create(DeviceImageCache *cache, const wchar_t *path, int width, int height,
DeviceImageLoader loader, void *loaderParam)
{
DeviceImage *self;
if (NULL == loader)
return NULL;
self = new DeviceImage();
if (NULL == self)
return NULL;
self->ref = 1;
self->cache = cache;
self->source = ResourceString_Duplicate(path);
self->loader = loader;
self->loaderParam = loaderParam;
self->bitmap = NULL;
self->exactBitmap = NULL;
self->width = width;
self->height = height;
return self;
}
static void
DeviceImage_Free(DeviceImage *self)
{
if (NULL == self)
return;
if (NULL != self->source)
ResourceString_Free(self->source);
if (NULL != self->bitmap)
DeleteObject(self->bitmap);
if (NULL != self->exactBitmap &&
self->exactBitmap != self->bitmap)
{
DeleteObject(self->exactBitmap);
}
delete(self);
}
static int
DeviceImageCache_SearchCb(const void *key, const void *element)
{
DeviceImageSeachParam *search;
DeviceImage *image;
int result;
search = (DeviceImageSeachParam*)key;
image = (DeviceImage*)element;
result = search->height - image->height;
if (0 != result)
return result;
result = search->width - image->width;
if (0 != result)
return result;
if (FALSE != IS_INTRESOURCE(search->path) ||
FALSE != IS_INTRESOURCE(image->source))
{
return (int)(INT_PTR)(search->path - image->source);
}
return CompareString(CSTR_INVARIANT, 0, search->path, -1, image->source, -1) - 2;
}
static int
DeviceImageCache_SortCb(const void *element1, const void *element2)
{
DeviceImage *image1;
DeviceImage *image2;
int result;
image1 = (DeviceImage*)element1;
image2 = (DeviceImage*)element2;
result = image1->height - image2->height;
if (0 != result)
return result;
result = image1->width - image2->width;
if (0 != result)
return result;
if (FALSE != IS_INTRESOURCE(image1->source) ||
FALSE != IS_INTRESOURCE(image2->source))
{
return (int)(INT_PTR)(image1->source - image2->source);
}
return CompareString(CSTR_INVARIANT, 0, image1->source, -1, image2->source, -1) - 2;
}
static int
DeviceImageCache_SortCb_V2(const void* element1, const void* element2)
{
return DeviceImageCache_SortCb(element1, element2) < 0;
}
static HBITMAP
DeviceImage_DefaultImageLoader(const wchar_t *path, int width, int height, void *param)
{
HBITMAP bitmap;
unsigned int flags;
flags = ISF_PREMULTIPLY;
if (FALSE == IS_INTRESOURCE(path))
flags |= ISF_LOADFROMFILE;
bitmap = Image_Load(path, SRC_TYPE_PNG, flags, 0, 0);
return bitmap;
}
DeviceImage *
DeviceImageCache_GetImage(DeviceImageCache *self, const wchar_t *path, int width, int height, DeviceImageLoader loader, void *user)
{
DeviceImage *image, *image_ptr = 0;
DeviceImageSeachParam searchParam;
if (width < 1)
width = 0;
if (height < 1)
height = 0;
if (NULL == self)
return NULL;
if (NULL == path ||
(FALSE == IS_INTRESOURCE(path) && L'\0' == *path))
{
return NULL;
}
searchParam.height = height;
searchParam.width = width;
searchParam.path = path;
//image_ptr = (DeviceImage**)bsearch(&searchParam, &self->list[0], self->list.size(),
// sizeof(DeviceImage**),
// DeviceImageCache_SearchCb);
auto it = std::find_if(self->list.begin(), self->list.end(),
[&](DeviceImage* upT) -> bool
{
return DeviceImageCache_SearchCb(&searchParam, upT) == 0;
}
);
if (it != self->list.end())
{
image_ptr = *it;
}
if (NULL != image_ptr)
{
image = image_ptr;
DeviceImage_AddRef(image);
return image;
}
if (NULL == loader)
loader = DeviceImage_DefaultImageLoader;
image = DeviceImage_Create(self, path, width, height, loader, user);
if (NULL != image)
{
self->list.push_back(image);
//qsort(&self->list[0], self->list.size(), sizeof(DeviceImage**), DeviceImageCache_SortCb);
std::sort(self->list.begin(), self->list.end(), DeviceImageCache_SortCb_V2);
}
return image;
}
static BOOL
DeviceImageCache_RemoveImage(DeviceImageCache *self, DeviceImage *image)
{
size_t index;
if (NULL == self || NULL == image)
return FALSE;
index = self->list.size();
while(index--)
{
if (self->list[index] == image)
{
self->list.erase(self->list.begin() + index);
return TRUE;
}
}
return FALSE;
}
size_t
DeviceImage_AddRef(DeviceImage *self)
{
if (NULL == self)
return 0;
return InterlockedIncrement((LONG*)&self->ref);
}
size_t
DeviceImage_Release(DeviceImage *self)
{
size_t r;
if (NULL == self || 0 == self->ref)
return 0;
r = InterlockedDecrement((LONG*)&self->ref);
if (0 == r)
{
if (NULL != self->cache)
DeviceImageCache_RemoveImage(self->cache, self);
DeviceImage_Free(self);
return 0;
}
return r;
}
BOOL
DeviceImage_GetSize(DeviceImage *self, int *width, int *height)
{
if (NULL == self)
return FALSE;
if (NULL != width)
*width = self->width;
if (NULL != height)
*height = self->height;
return TRUE;
}
static IWICImagingFactory*
DeviceImage_GetWicFactory(DeviceImageCache *cache)
{
IWICImagingFactory *wicFactory;
HRESULT hr;
if (NULL != cache &&
NULL != cache->wicFactory)
{
cache->wicFactory->AddRef();
return cache->wicFactory;
}
hr = CoCreateInstance(CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
IID_PPV_ARGS(&wicFactory));
if (FAILED(hr))
return NULL;
if (NULL != cache)
{
wicFactory->AddRef();
cache->wicFactory = wicFactory;
}
return wicFactory;
}
static HBITMAP
DeviceImage_HBitmapFromWicSource(IWICBitmapSource *wicSource, unsigned int targetWidth,
unsigned int targetHeight, DeviceImageFlags flags)
{
HRESULT hr;
HBITMAP bitmap;
BITMAPINFO bitmapInfo;
unsigned int width, height, bitmapWidth, bitmapHeight;
void *pixelData = NULL;
WICPixelFormatGUID pixelFormat;
HDC windowDC;
unsigned int strideSize, imageSize;
if (NULL == wicSource)
return NULL;
hr = wicSource->GetPixelFormat(&pixelFormat);
if (FAILED(hr) ||
(GUID_WICPixelFormat32bppPBGRA != pixelFormat &&
GUID_WICPixelFormat32bppBGR != pixelFormat &&
GUID_WICPixelFormat32bppBGRA != pixelFormat &&
GUID_WICPixelFormat32bppRGBA != pixelFormat &&
GUID_WICPixelFormat32bppPRGBA != pixelFormat))
{
return NULL;
}
hr = wicSource->GetSize(&width, &height);
if (FAILED(hr))
return NULL;
if (0 != (DeviceImage_ExactSize & flags))
{
bitmapWidth = (targetWidth > width) ? targetWidth : width;
bitmapHeight = (targetHeight > height) ? targetHeight : height;
}
else
{
bitmapWidth = width;
bitmapHeight = height;
}
ZeroMemory(&bitmapInfo, sizeof(bitmapInfo));
bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bitmapInfo.bmiHeader.biWidth = bitmapWidth;
bitmapInfo.bmiHeader.biHeight = -(LONG)bitmapHeight;
bitmapInfo.bmiHeader.biPlanes = 1;
bitmapInfo.bmiHeader.biBitCount = 32;
bitmapInfo.bmiHeader.biCompression = BI_RGB;
windowDC = GetDCEx(NULL, NULL, DCX_WINDOW | DCX_CACHE);
bitmap = CreateDIBSection(windowDC, &bitmapInfo, DIB_RGB_COLORS, &pixelData, NULL, 0);
if (NULL != windowDC)
ReleaseDC(NULL, windowDC);
if (NULL == bitmap)
return NULL;
hr = UIntMult(bitmapWidth, sizeof(DWORD), &strideSize);
if (SUCCEEDED(hr))
{
if (0 != (DeviceImage_ExactSize & flags) &&
(bitmapWidth > width || bitmapHeight > height))
{
if (SUCCEEDED(UIntMult(strideSize, bitmapHeight, &imageSize)))
ZeroMemory(pixelData, imageSize);
}
hr = UIntMult(strideSize, height, &imageSize);
if (SUCCEEDED(hr))
{
unsigned int offset, delta;
offset = 0;
if (0 != (DeviceImage_AlignVCenter & flags))
{
delta = bitmapHeight - height;
delta = delta/2 + delta%2;
}
else if (0 != (DeviceImage_AlignBottom & flags))
delta = bitmapHeight - height;
else
delta = 0;
if (0 != delta && SUCCEEDED(UIntMult(delta, strideSize, &delta)))
offset += delta;
if (0 != (DeviceImage_AlignHCenter & flags))
{
delta = bitmapWidth - width;
delta = delta/2;
}
else if (0 != (DeviceImage_AlignRight & flags))
delta = bitmapWidth - width;
else
delta = 0;
if (0 != delta && SUCCEEDED(UIntMult(delta, sizeof(DWORD), &delta)))
offset += delta;
hr = wicSource->CopyPixels(NULL, strideSize, imageSize, ((BYTE*)pixelData) + offset);
}
}
if (FAILED(hr))
{
DeleteObject(bitmap);
bitmap = NULL;
}
return bitmap;
}
static BOOL
DeviceImage_ScaleBitmap(HBITMAP sourceBitmap, int width, int height, DeviceImageCache *cache,
DeviceImageFlags flags, HBITMAP *scalledBitmap)
{
HBITMAP resultBitmap;
BITMAP sourceInfo;
IWICImagingFactory *wicFactory;
unsigned int requestedWidth, requestedHeight;
double scale, scaleH;
int t;
if (NULL == sourceBitmap || NULL == scalledBitmap)
return FALSE;
if (sizeof(sourceInfo) != GetObject(sourceBitmap, sizeof(sourceInfo), &sourceInfo))
return FALSE;
if (sourceInfo.bmHeight < 0)
sourceInfo.bmHeight = -sourceInfo.bmHeight;
scale = (double)width / sourceInfo.bmWidth;
scaleH = (double)height / sourceInfo.bmHeight;
if (scale > scaleH)
scale = scaleH;
if (1.0 == scale)
{
*scalledBitmap = NULL;
return TRUE;
}
requestedWidth = width;
requestedHeight = height;
t = (int)((sourceInfo.bmWidth * scale) + 0.5);
if (t < width)
width = t;
t = (int)((sourceInfo.bmHeight * scale) + 0.5);
if (t < height)
height = t;
resultBitmap = NULL;
wicFactory = DeviceImage_GetWicFactory(cache);
if (NULL != wicFactory)
{
HRESULT hr;
IWICBitmap *wicBitmap;
hr = wicFactory->CreateBitmapFromHBITMAP(sourceBitmap, NULL,
WICBitmapUsePremultipliedAlpha, &wicBitmap);
if (SUCCEEDED(hr))
{
IWICBitmapScaler *wicScaler;
hr = wicFactory->CreateBitmapScaler(&wicScaler);
if (SUCCEEDED(hr))
{
hr = wicScaler->Initialize(wicBitmap, width, height, WICBitmapInterpolationModeFant);
if (SUCCEEDED(hr))
{
resultBitmap = DeviceImage_HBitmapFromWicSource(wicScaler,
requestedWidth, requestedHeight, flags);
}
wicScaler->Release();
}
wicBitmap->Release();
}
wicFactory->Release();
}
*scalledBitmap = resultBitmap;
return (NULL != resultBitmap);
}
static HBITMAP
DeviceImage_GetExactBitmap(DeviceImage *self, DeviceImageFlags flags)
{
if (NULL == self)
return NULL;
if (NULL == self->exactBitmap)
{
if (NULL != self->bitmap)
{
BITMAP bi;
if (sizeof(bi) == GetObject(self->bitmap, sizeof(bi), &bi) &&
bi.bmWidth == self->width && bi.bmHeight == self->height)
{
self->exactBitmap = self->bitmap;
return self->exactBitmap;
}
}
if (NULL != self->loader)
{
HBITMAP bitmap;
bitmap = self->loader(self->source, self->width, self->height, self->loaderParam);
if (NULL != bitmap)
{
if (FALSE != DeviceImage_ScaleBitmap(bitmap, self->width, self->height,
self->cache, flags, &self->exactBitmap))
{
if (NULL == self->exactBitmap)
{
self->exactBitmap = bitmap;
bitmap = NULL;
}
}
if (NULL != bitmap)
DeleteObject(bitmap);
}
}
}
return self->exactBitmap;
}
HBITMAP
DeviceImage_GetBitmap(DeviceImage *self, DeviceImageFlags flags)
{
if (NULL == self)
return NULL;
if (0 != (DeviceImage_ExactSize & flags))
return DeviceImage_GetExactBitmap(self, flags);
if (NULL == self->bitmap)
{
if (NULL != self->loader)
{
HBITMAP bitmap;
bitmap = self->loader(self->source, self->width, self->height, self->loaderParam);
if (NULL != bitmap)
{
if (FALSE == DeviceImage_ScaleBitmap(bitmap, self->width, self->height,
self->cache, flags, &self->bitmap))
{
self->bitmap = NULL;
}
if (NULL != self->bitmap)
DeleteObject(bitmap);
else
self->bitmap = bitmap;
}
}
}
return self->bitmap;
}
static DeviceColoredImage *
DeveiceColoredImage_Create(DeviceImage *base, COLORREF color1, COLORREF color2,
DeviceImageFilter filter, void *user)
{
DeviceColoredImage *coloredImage;
if (NULL == base)
return NULL;
coloredImage = (DeviceColoredImage*)malloc(sizeof(DeviceColoredImage));
if (NULL == coloredImage)
return NULL;
ZeroMemory(coloredImage, sizeof(DeviceColoredImage));
coloredImage->ref = 1;
coloredImage->base = base;
coloredImage->color1 = color1;
coloredImage->color2 = color2;
coloredImage->filter = filter;
coloredImage->filterParam = user;
DeviceImage_AddRef(base);
return coloredImage;
}
static void
DeviceColoredImage_Free(DeviceColoredImage *self)
{
if (NULL == self)
return;
if (NULL != self->bitmap)
DeleteObject(self->bitmap);
free(self);
}
static int
DeviceColoredImage_SearchCb(const void *key, const void *element)
{
DeviceColoredImageSeachParam *search;
DeviceColoredImage *image;
int result;
search = (DeviceColoredImageSeachParam*)key;
image = (DeviceColoredImage*)element;
result = search->color1 - image->color1;
if (0 != result)
return result;
return search->color2- image->color2;
}
static int
DeviceColoredImage_SortCb(const void *element1, const void *element2)
{
DeviceColoredImage *image1;
DeviceColoredImage *image2;
int result;
image1 = (DeviceColoredImage*)element1;
image2 = (DeviceColoredImage*)element2;
result = image1->color1 - image2->color1;
if (0 != result)
return result;
return image1->color2- image2->color2;
}
static int
DeviceColoredImage_SortCb_V2(const void* element1, const void* element2)
{
return DeviceColoredImage_SortCb(element1, element2) < 0;
}
DeviceColoredImage *
DeviceImage_GetColoredImage(DeviceImage *self, COLORREF color1, COLORREF color2,
DeviceImageFilter filter, void *user)
{
size_t listSize;
DeviceColoredImage *image;
DeviceColoredImageSeachParam searchParam;
searchParam.color1 = color1;
searchParam.color2 = color2;
listSize = self->list.size();
if (listSize > 0)
{
DeviceColoredImage* image_ptr = NULL;
//DeviceColoredImage **image_ptr = (DeviceColoredImage**)bsearch(&searchParam, &self->list[0], listSize,
// sizeof(DeviceColoredImage**),
// DeviceColoredImage_SearchCb);
auto it = std::find_if(self->list.begin(), self->list.end(),
[&](DeviceColoredImage* upT) -> bool
{
return DeviceColoredImage_SearchCb(&searchParam, upT) == 0;
}
);
if (it != self->list.end())
{
image_ptr = *it;
}
if (NULL != image_ptr)
{
image = image_ptr;
DeviceColoredImage_AddRef(image);
return image;
}
}
image = DeveiceColoredImage_Create(self, color1, color2, filter, user);
if (NULL == image)
return NULL;
self->list.push_back(image);
listSize++;
if (listSize > 1)
{
//qsort(&self->list[0], self->list.size(), sizeof(DeviceColoredImage**),
// DeviceColoredImage_SortCb);
std::sort(self->list.begin(), self->list.end(), DeviceColoredImage_SortCb_V2);
}
return image;
}
static void
DeviceImage_RemoveColored(DeviceImage *self, DeviceColoredImage *coloredImage)
{
size_t index;
if (NULL == self || NULL == coloredImage)
return;
index = self->list.size();
while(index--)
{
if (coloredImage == self->list[index])
{
self->list.erase(self->list.begin() + index);
}
}
}
size_t
DeviceColoredImage_AddRef(DeviceColoredImage *self)
{
if (NULL == self)
return 0;
return InterlockedIncrement((LONG*)&self->ref);
}
size_t
DeviceColoredImage_Release(DeviceColoredImage *self)
{
size_t r;
if (NULL == self || 0 == self->ref)
return 0;
r = InterlockedDecrement((LONG*)&self->ref);
if (0 == r)
{
if (NULL != self->base)
{
DeviceImage_RemoveColored(self->base, self);
DeviceImage_Release(self->base);
}
DeviceColoredImage_Free(self);
return 0;
}
return r;
}
static BOOL
DeviceColoredImage_DefaultFilter(HBITMAP bitmap, COLORREF color1, COLORREF color2, void *user)
{
DIBSECTION bitmapDib;
BITMAP *bitmapInfo;
MLIMAGEFILTERAPPLYEX filter;
if (sizeof(bitmapDib) != GetObjectW(bitmap, sizeof(bitmapDib), &bitmapDib))
return FALSE;
bitmapInfo = &bitmapDib.dsBm;
filter.cbSize = sizeof(filter);
filter.pData = (BYTE*)bitmapInfo->bmBits;
filter.cx = bitmapInfo->bmWidth;
filter.cy = bitmapInfo->bmHeight;
filter.bpp = bitmapInfo->bmBitsPixel;
filter.imageTag = NULL;
filter.filterUID = MLIF_GRAYSCALE_UID;
MLImageFilter_ApplyEx(Plugin_GetLibraryWindow(), &filter);
filter.rgbBk = color1;
filter.rgbFg = color2;
if (32 == bitmapInfo->bmBitsPixel)
{
filter.filterUID = MLIF_FILTER1_PRESERVE_ALPHA_UID;
MLImageFilter_ApplyEx(Plugin_GetLibraryWindow(), &filter);
}
else
{
filter.filterUID = MLIF_FILTER1_UID;
MLImageFilter_ApplyEx(Plugin_GetLibraryWindow(), &filter);
}
return TRUE;
}
HBITMAP
DeviceColoredImage_GetBitmap(DeviceColoredImage *self, DeviceImageFlags flags)
{
if (NULL == self)
return NULL;
if (NULL == self->bitmap)
{
HBITMAP bitmap;
bitmap = DeviceImage_GetBitmap(self->base, flags);
if (NULL != bitmap)
{
self->bitmap = Image_DuplicateDib(bitmap);
if (NULL != self->bitmap)
{
DeviceImageFilter filter;
if (NULL == self->filter)
filter = DeviceColoredImage_DefaultFilter;
else
filter = self->filter;
Image_Demultiply(self->bitmap, NULL);
filter(self->bitmap, self->color1, self->color2, self->filterParam);
Image_Premultiply(self->bitmap, NULL);
}
}
}
return self->bitmap;
}
DeviceImage*
DeviceColoredImage_GetBaseImage(DeviceColoredImage *self)
{
if (NULL == self || NULL == self->base)
return NULL;
DeviceImage_AddRef(self->base);
return self->base;
}

Some files were not shown because too many files have changed in this diff Show More