aboutsummaryrefslogtreecommitdiff
path: root/Src/Plugins/General/gen_tray
diff options
context:
space:
mode:
Diffstat (limited to 'Src/Plugins/General/gen_tray')
-rw-r--r--Src/Plugins/General/gen_tray/GEN_TRAY.sln30
-rw-r--r--Src/Plugins/General/gen_tray/GEN_TRAY.vcxproj296
-rw-r--r--Src/Plugins/General/gen_tray/GEN_TRAY.vcxproj.filters64
-rw-r--r--Src/Plugins/General/gen_tray/RESOURCE.H66
-rw-r--r--Src/Plugins/General/gen_tray/TRAYCTL.C1526
-rw-r--r--Src/Plugins/General/gen_tray/WINAMPCMD.H62
-rw-r--r--Src/Plugins/General/gen_tray/api__gen_tray.h8
-rw-r--r--Src/Plugins/General/gen_tray/gen_tray.rc178
-rw-r--r--Src/Plugins/General/gen_tray/icons/compact.bmpbin0 -> 126 bytes
-rw-r--r--Src/Plugins/General/gen_tray/icons/icon1.icobin0 -> 318 bytes
-rw-r--r--Src/Plugins/General/gen_tray/icons/icon2.icobin0 -> 318 bytes
-rw-r--r--Src/Plugins/General/gen_tray/icons/icon3.icobin0 -> 318 bytes
-rw-r--r--Src/Plugins/General/gen_tray/icons/icon4.icobin0 -> 318 bytes
-rw-r--r--Src/Plugins/General/gen_tray/icons/icon5.icobin0 -> 318 bytes
-rw-r--r--Src/Plugins/General/gen_tray/icons/icon7.icobin0 -> 318 bytes
-rw-r--r--Src/Plugins/General/gen_tray/icons/icon8.icobin0 -> 318 bytes
-rw-r--r--Src/Plugins/General/gen_tray/icons/icon9.icobin0 -> 318 bytes
-rw-r--r--Src/Plugins/General/gen_tray/version.rc239
18 files changed, 2269 insertions, 0 deletions
diff --git a/Src/Plugins/General/gen_tray/GEN_TRAY.sln b/Src/Plugins/General/gen_tray/GEN_TRAY.sln
new file mode 100644
index 00000000..51910ecb
--- /dev/null
+++ b/Src/Plugins/General/gen_tray/GEN_TRAY.sln
@@ -0,0 +1,30 @@
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.29424.173
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gen_tray", "GEN_TRAY.vcxproj", "{DD15E699-90D2-4301-921A-7C2C48B25766}"
+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
+ {DD15E699-90D2-4301-921A-7C2C48B25766}.Debug|Win32.ActiveCfg = Debug|Win32
+ {DD15E699-90D2-4301-921A-7C2C48B25766}.Debug|Win32.Build.0 = Debug|Win32
+ {DD15E699-90D2-4301-921A-7C2C48B25766}.Debug|x64.ActiveCfg = Debug|x64
+ {DD15E699-90D2-4301-921A-7C2C48B25766}.Debug|x64.Build.0 = Debug|x64
+ {DD15E699-90D2-4301-921A-7C2C48B25766}.Release|Win32.ActiveCfg = Release|Win32
+ {DD15E699-90D2-4301-921A-7C2C48B25766}.Release|Win32.Build.0 = Release|Win32
+ {DD15E699-90D2-4301-921A-7C2C48B25766}.Release|x64.ActiveCfg = Release|x64
+ {DD15E699-90D2-4301-921A-7C2C48B25766}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {9B581402-0754-4899-8AEE-E886596F3A19}
+ EndGlobalSection
+EndGlobal
diff --git a/Src/Plugins/General/gen_tray/GEN_TRAY.vcxproj b/Src/Plugins/General/gen_tray/GEN_TRAY.vcxproj
new file mode 100644
index 00000000..b6287a69
--- /dev/null
+++ b/Src/Plugins/General/gen_tray/GEN_TRAY.vcxproj
@@ -0,0 +1,296 @@
+<?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">
+ <ProjectName>gen_tray</ProjectName>
+ <ProjectGuid>{DD15E699-90D2-4301-921A-7C2C48B25766}</ProjectGuid>
+ <RootNamespace>gen_tray</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)'=='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)'=='Release|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)'=='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>
+ <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">
+ <VcpkgEnabled>false</VcpkgEnabled>
+ </PropertyGroup>
+ <PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <VcpkgConfiguration>Debug</VcpkgConfiguration>
+ </PropertyGroup>
+ <PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <VcpkgConfiguration>Debug</VcpkgConfiguration>
+ </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;GEN_TRAY_EXPORTS;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>false</MinimalRebuild>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <BufferSecurityCheck>true</BufferSecurityCheck>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX86</TargetMachine>
+ <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <SubSystem>Windows</SubSystem>
+ </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>
+ </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;GEN_TRAY_EXPORTS;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>false</MinimalRebuild>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <BufferSecurityCheck>true</BufferSecurityCheck>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <SubSystem>Windows</SubSystem>
+ </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>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <Optimization>MinSpace</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <AdditionalIncludeDirectories>.;..\..\..\Wasabi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;WIN32;NDEBUG;_WINDOWS;_USRDLL;GEN_TRAY_EXPORTS;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <BufferSecurityCheck>true</BufferSecurityCheck>
+ <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>None</DebugInformationFormat>
+ <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX86</TargetMachine>
+ <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <SubSystem>Windows</SubSystem>
+ </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>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <Optimization>MinSpace</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <AdditionalIncludeDirectories>.;..\..\..\Wasabi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;WIN64;NDEBUG;_WINDOWS;_USRDLL;GEN_TRAY_EXPORTS;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <BufferSecurityCheck>true</BufferSecurityCheck>
+ <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>None</DebugInformationFormat>
+ <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <SubSystem>Windows</SubSystem>
+ </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>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClInclude Include="api__gen_tray.h" />
+ <ClInclude Include="RESOURCE.H" />
+ <ClInclude Include="WINAMPCMD.H" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="TRAYCTL.C">
+ <CompileAs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CompileAsCpp</CompileAs>
+ <CompileAs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CompileAsCpp</CompileAs>
+ <CompileAs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">CompileAsCpp</CompileAs>
+ <CompileAs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">CompileAsCpp</CompileAs>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <Image Include="icons\compact.bmp" />
+ <Image Include="icons\icon1.ico" />
+ <Image Include="icons\icon2.ico" />
+ <Image Include="icons\icon3.ico" />
+ <Image Include="icons\icon4.ico" />
+ <Image Include="icons\icon5.ico" />
+ <Image Include="icons\icon7.ico" />
+ <Image Include="icons\icon8.ico" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="gen_tray.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> \ No newline at end of file
diff --git a/Src/Plugins/General/gen_tray/GEN_TRAY.vcxproj.filters b/Src/Plugins/General/gen_tray/GEN_TRAY.vcxproj.filters
new file mode 100644
index 00000000..40a2e389
--- /dev/null
+++ b/Src/Plugins/General/gen_tray/GEN_TRAY.vcxproj.filters
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <ClInclude Include="api__gen_tray.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="RESOURCE.H">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="WINAMPCMD.H">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <Image Include="icons\icon1.ico">
+ <Filter>Image Files</Filter>
+ </Image>
+ <Image Include="icons\icon2.ico">
+ <Filter>Image Files</Filter>
+ </Image>
+ <Image Include="icons\icon3.ico">
+ <Filter>Image Files</Filter>
+ </Image>
+ <Image Include="icons\icon4.ico">
+ <Filter>Image Files</Filter>
+ </Image>
+ <Image Include="icons\icon5.ico">
+ <Filter>Image Files</Filter>
+ </Image>
+ <Image Include="icons\icon7.ico">
+ <Filter>Image Files</Filter>
+ </Image>
+ <Image Include="icons\icon8.ico">
+ <Filter>Image Files</Filter>
+ </Image>
+ <Image Include="icons\compact.bmp">
+ <Filter>Image Files</Filter>
+ </Image>
+ </ItemGroup>
+ <ItemGroup>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{96125085-f1a0-41bb-a9be-181833e83c26}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Ressource Files">
+ <UniqueIdentifier>{79c08881-db4b-4236-bf7d-aedeb08c65b2}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{642a812f-646c-4a9b-ba39-93c8405dcf96}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Image Files">
+ <UniqueIdentifier>{ec91a377-7c2d-47f3-8508-27f333a2c638}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="gen_tray.rc">
+ <Filter>Ressource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="TRAYCTL.C">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/Src/Plugins/General/gen_tray/RESOURCE.H b/Src/Plugins/General/gen_tray/RESOURCE.H
new file mode 100644
index 00000000..b0425e8b
--- /dev/null
+++ b/Src/Plugins/General/gen_tray/RESOURCE.H
@@ -0,0 +1,66 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by SCRIPT1.RC
+//
+#define IDS_PREVIOUS_TRACK 0
+#define IDS_PLAY_PAUSE 1
+#define IDS_STOP 2
+#define IDC_APPLY 3
+#define IDS_NEXT_TRACK 3
+#define IDS_OPEN_FILE 4
+#define IDS_COMPACT_MODE 5
+#define IDS_DECREASE_VOLUME 6
+#define IDS_INCREASE_VOLUME 7
+#define IDS_HOLD_CTRL 8
+#define IDS_HOLD_SHIFT 9
+// #define IDS_WIN2K_PLUS 10
+#define IDS_CTRL_TO_DECREASE 11
+#define IDS_CTRL_TO_INCREASE 12
+#define IDS_STOPPED_STR 13
+#define IDS_PAUSED_STR 14
+#define IDS_DEFAULT_ICONS 15
+#define IDS_CUSTOM_ICON_PACK 16
+#define IDS_CONFIG_INFO 17
+#define IDS_OFD_FILTER_STR 18
+#define IDS_OFD_TITLE_STR 19
+#define IDS_STRING22 20
+#define IDS_GET_ICON_PACKS 21
+#define IDS_DO_YOU_ALSO_WANT_TO_REMOVE_SETTINGS 22
+#define IDD_DIALOG1 101
+#define IDD_DIALOG2 102
+#define IDI_ICON1 103
+#define IDI_ICON2 104
+#define IDI_ICON3 105
+#define IDI_ICON4 106
+#define IDI_ICON5 107
+#define IDI_ICON6 108
+#define IDI_ICON7 109
+#define IDI_ICON8 110
+#define IDB_BITMAP1 111
+#define IDC_ONOFF 1000
+#define IDC_PREV 1001
+#define IDC_PREV2 1002
+#define IDC_PREV3 1003
+#define IDC_PREV4 1004
+#define IDC_PREV5 1005
+#define IDC_PREV6 1006
+#define IDC_PREV7 1007
+#define IDC_PREV8 1008
+#define IDC_COMBO1 1009
+#define IDC_EDIT1 1010
+#define IDC_BUTTON1 1011
+#define ID_INFO 1012
+#define IDC_COMBO2 1013
+#define IDC_LINK 1014
+#define IDS_NULLSOFT_TRAY_CONTROL 65534
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 117
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1015
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/Src/Plugins/General/gen_tray/TRAYCTL.C b/Src/Plugins/General/gen_tray/TRAYCTL.C
new file mode 100644
index 00000000..43725e62
--- /dev/null
+++ b/Src/Plugins/General/gen_tray/TRAYCTL.C
@@ -0,0 +1,1526 @@
+#define PLUGIN_NAME L"Nullsoft Tray Control"
+#define PLUGIN_VERSION L"2.49"
+
+// Winamp general purpose plug-in mini-SDK
+// Copyright (C) 1997, Justin Frankel/Nullsoft
+// Modifications and useability enhancements by DrO aka Darren Owen 2006-2014
+#include <windows.h>
+#include <commctrl.h>
+#include <shlwapi.h>
+#include "../winamp/gen.h"
+#include "../winamp/wa_ipc.h"
+#include "../winamp/ipc_pe.h"
+#include "resource.h"
+#include "winampcmd.h"
+#include "api__gen_tray.h"
+#include <strsafe.h>
+
+
+#ifndef _DEBUG
+BOOL WINAPI _DllMainCRTStartup(HINSTANCE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
+{
+ DisableThreadLibraryCalls(hInst);
+ return TRUE;
+}
+#endif
+
+
+#define NUM_ICONS 8
+#define FOURWAY_NUM 7
+#define SYSTRAY_ICON_BASE 1024
+
+// used for Win7+ usage inorder to get the direct location of the icon instead of the prior hacks (thanks MS!)
+typedef HRESULT (WINAPI *SHELL_NOTIFYICONGETRECT)(const NOTIFYICONIDENTIFIER* identifier, RECT* iconLocation);
+SHELL_NOTIFYICONGETRECT g_Shell_NotifyIconGetRect = 0;
+
+// Use a guid to uniquely identify our icon
+class __declspec(uuid("B4E5FE9B-6A22-450e-9565-941EF50CFEEB")) CompactIcon;
+
+
+// wasabi based services for localisation support
+api_service *WASABI_API_SVC = 0;
+api_language *WASABI_API_LNG = 0;
+HINSTANCE WASABI_API_LNG_HINST = 0, WASABI_API_ORIG_HINST = 0;
+
+int config_enabled = 0,
+ xporhigher = 0,
+ custom_enabled = 0,
+ winver = 0,
+ flip = 0,
+ on = 1,
+ update_file = 0,
+ isX64 = 0,
+ no_uninstall = 1,
+ dlg_init = 0;
+
+UINT s_uTaskbarRestart=0;
+HWND configwnd = 0;
+WNDPROC lpWndProcOld = 0;
+HICON Icons[NUM_ICONS] = {0}, dummyIcon = 0;
+HBITMAP compact = 0;
+fileinfo2W file = {0};
+
+wchar_t ico_pack[MAX_PATH] = {0},
+ ico_pack_base[MAX_PATH] = {0},
+ ico_pack_safe[MAX_PATH] = {0},
+ wa_path[MAX_PATH] = {0},
+ *ini_file = 0,
+ szDescription[256] = {0};
+
+int tips[NUM_ICONS] = {
+ IDS_PREVIOUS_TRACK,
+ IDS_PLAY_PAUSE,
+ IDS_STOP,
+ IDS_NEXT_TRACK,
+ IDS_OPEN_FILE,
+ IDS_COMPACT_MODE,
+ IDS_DECREASE_VOLUME,
+ IDS_INCREASE_VOLUME,
+};
+
+int tips_ex[NUM_ICONS] = {
+ IDS_HOLD_CTRL,
+ IDS_HOLD_CTRL,
+ IDS_HOLD_SHIFT,
+ -1,
+ -1,
+// IDS_WIN2K_PLUS,
+ -1,
+ IDS_CTRL_TO_DECREASE,
+ IDS_CTRL_TO_INCREASE,
+};
+
+LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
+BOOL CALLBACK ConfigProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam);
+HICON CreateInternalIcon(void);
+int FileExists(char* filename);
+void config(void);
+void quit(void);
+int init(void);
+void config_write();
+void config_read();
+
+extern "C" winampGeneralPurposePlugin plugin =
+{
+ GPPHDR_VER_U,
+ "nullsoft(gen_tray.dll)",
+ init,
+ config,
+ quit,
+};
+
+extern "C" __declspec(dllexport) winampGeneralPurposePlugin * winampGetGeneralPurposePlugin() { return &plugin; }
+
+
+HWND GetPlaylistWnd(HWND winamp){
+HWND pl_wnd = 0;
+
+ // get the playlist editor window (either v2.9x method or the older
+ // for compatibility incase < 2.9x are used
+ if(SendMessage(winamp,WM_WA_IPC,0,IPC_GETVERSION) >= 0x2900)
+ {
+ pl_wnd = (HWND)SendMessage(winamp,WM_WA_IPC,IPC_GETWND_PE,IPC_GETWND);
+ }
+ if(!pl_wnd)
+ {
+ pl_wnd = FindWindow(L"Winamp PE",0);
+ }
+ return pl_wnd;
+}
+
+void FormCompactText(wchar_t* szTip, int szTipLength){
+int got = 0;
+
+ // only update if we really have to (to better mimick Winamp's title behaviour, etc)
+ // otherwise we query in all cases which can often reflect what appears to be the wrong information since
+ // the current playlist entry is altered, etc on playlist modification hence an incorrect observation
+ if(!update_file){
+ update_file = 1;
+ file.fileindex = (int)SendMessage(GetPlaylistWnd(plugin.hwndParent),WM_WA_IPC,IPC_PE_GETCURINDEX,0);
+ got = (int)SendMessage(GetPlaylistWnd(plugin.hwndParent),WM_WA_IPC,IPC_PE_GETINDEXTITLEW,(LPARAM)&file);
+ }
+
+ // if it returns 0 then track information was received
+ if(!got && file.filetitle[0]){
+ int time = (int)SendMessage(plugin.hwndParent,WM_WA_IPC,0,IPC_GETOUTPUTTIME);
+ wchar_t buf[MAX_PATH*2] = {0}, temp[1024] = {0}, *t = temp, *p = 0;
+ int over = 0, state = 0, blah = 0;
+ wchar_t stateStr[32] = {0};
+
+ switch(SendMessage(plugin.hwndParent,WM_WA_IPC,0,IPC_ISPLAYING)){
+ case 0:
+ WASABI_API_LNGSTRINGW_BUF(IDS_STOPPED_STR,stateStr,32);
+ state = lstrlen(stateStr);
+ break;
+ case 3:
+ WASABI_API_LNGSTRINGW_BUF(IDS_PAUSED_STR,stateStr,32);
+ state = lstrlen(stateStr);
+ break;
+ }
+
+ p = file.filetitle;
+ while(p && *p){
+ *t++ = *p++;
+ if(*(p-1) == '&'){
+ *t++ = '&';
+ *t++ = '&';
+ }
+ }
+ *t = 0;
+
+ StringCchPrintf(buf,MAX_PATH*2,L"%d. %s",(file.fileindex)+1,file.filetitle);
+ over = lstrlen(buf);
+ if(over > szTipLength - 1){over = szTipLength - 1;}
+ lstrcpyn(szTip,buf,szTipLength);
+
+ if(time != -1){
+ time = time/1000;
+
+ if(file.filelength[0]){
+ StringCchPrintf(buf,MAX_PATH*2,L" [%02d:%02d/%s]",(time/60),time%60,file.filelength);
+ blah = lstrlen(buf);
+ }
+ else{
+ StringCchPrintf(buf,MAX_PATH*2,L" [%02d:%02d]",(time/60),time%60);
+ blah = lstrlen(buf);
+ }
+ }
+
+ if((over + blah + state) > szTipLength){
+ int adj = szTipLength-blah-state-1;
+ szTip[adj] = 0;
+ szTip[adj-1] = L'.';
+ szTip[adj-2] = L'.';
+ szTip[adj-3] = L'.';
+ }
+
+ if(time != -1){
+ StringCchCat(szTip,szTipLength,buf);
+ }
+
+ if(state){
+ StringCchCat(szTip,szTipLength,stateStr);
+ }
+ }
+
+ // fall back to the Winamp version just incase
+ else{
+ wchar_t temp[16] = {0};
+ StringCchPrintf(temp,16,L"%X",SendMessage(plugin.hwndParent,WM_WA_IPC,0,IPC_GETVERSION));
+ StringCchPrintf(szTip,szTipLength,L"Winamp %c.%s",temp[0],&temp[2]);
+ }
+}
+
+void free_icons(void){
+int i = 0;
+ for (i = 0; i < NUM_ICONS; i++)
+ {
+ if( Icons[i] ) {
+ DestroyIcon(Icons[i]);
+ Icons[i] = 0;
+ }
+ }
+
+ if(dummyIcon) {
+ DestroyIcon(dummyIcon);
+ dummyIcon = 0;
+ }
+
+ if(compact) {
+ DeleteObject(compact);
+ }
+}
+
+void do_icons(int force)
+{
+ static int l=0;
+ int i=NUM_ICONS;
+
+ if (l == config_enabled && !force) return;
+
+ if( force ) free_icons();
+
+ while (i--)
+ {
+ if (l & (1<<i))
+ {
+ NOTIFYICONDATAW tnid={0};
+ tnid.cbSize=sizeof(NOTIFYICONDATAW);
+ tnid.hWnd=plugin.hwndParent;
+ tnid.uID=i+SYSTRAY_ICON_BASE;
+ Shell_NotifyIcon(NIM_DELETE, &tnid);
+ }
+ }
+
+ l=config_enabled;
+
+ if(!on) {return;}
+
+ // have to do XP+ specific changes here in order for the icon addition order to appear as expected and not back to front!
+ for (i = (xporhigher?(NUM_ICONS-1):0); (xporhigher?i>-1:i < NUM_ICONS); (xporhigher?i --:i ++))
+ {
+ if (config_enabled & (1<<i))
+ {
+ // check if an icon pack has not been set or it's not a valid file that's being passed
+ // if so then need to use the default icons
+ if (!ico_pack[0] || !PathFileExists(ico_pack) )
+ {
+ if (!Icons[i]) Icons[i] = LoadIcon(plugin.hDllInstance,MAKEINTRESOURCE(IDI_ICON1+i));
+ if (i == 5) {
+ compact = (HBITMAP)LoadImage(plugin.hDllInstance,MAKEINTRESOURCE(IDB_BITMAP1),IMAGE_BITMAP,0,0,LR_SHARED);
+ Icons[i] = CreateInternalIcon();
+ }
+ }
+ else
+ {
+ wchar_t* icpb = 0;
+ lstrcpyn(ico_pack_base,ico_pack,ARRAYSIZE(ico_pack_base));
+ icpb = ico_pack_base + lstrlen(ico_pack_base) - 1;
+ while(icpb && *icpb && *icpb != L'\\'){icpb = CharPrev(ico_pack,icpb);}
+ if (icpb) *icpb = 0;
+
+ if (!Icons[i]){
+ wchar_t entry[MAX_PATH] = {0}, buf[MAX_PATH] = {0};
+ int compact_loaded = 0;
+
+ StringCchPrintf(entry,MAX_PATH,L"ico%d",i+1);
+ GetPrivateProfileString(L"tray icon pack",entry,buf,buf,ARRAYSIZE(buf),ico_pack);
+ StringCchPrintf(entry,MAX_PATH,L"%s\\%s",ico_pack_base,buf);
+
+ Icons[i] = (HICON)LoadImage(0,entry,(i != 5?IMAGE_ICON:IMAGE_BITMAP),0,0,LR_LOADFROMFILE|LR_SHARED);
+ if (i == 5) {
+ compact = (HBITMAP)Icons[i];
+ if(compact) {
+ compact_loaded = 1;
+ }
+ }
+ // if this fails then we use the built-in versions
+ if (!Icons[i]) Icons[i] = LoadIcon(plugin.hDllInstance,MAKEINTRESOURCE(IDI_ICON1+i));
+ if (i == 5) {
+ if (!compact_loaded) {
+ compact = (HBITMAP)LoadImage(plugin.hDllInstance,MAKEINTRESOURCE(IDB_BITMAP1),IMAGE_BITMAP,0,0,LR_SHARED);
+ }
+ Icons[i] = CreateInternalIcon();
+ }
+ }
+ }
+
+ {
+ NOTIFYICONDATAW tnid={0};
+ tnid.cbSize=sizeof(NOTIFYICONDATAW);
+ tnid.hWnd=plugin.hwndParent;
+ tnid.uID=i+SYSTRAY_ICON_BASE;
+ tnid.uFlags=NIF_ICON | NIF_TIP | NIF_MESSAGE | NIF_GUID;
+ tnid.uCallbackMessage=WM_USER + 2707;
+ tnid.hIcon=Icons[i];
+ if(i != 5)
+ StringCchPrintf(tnid.szTip,sizeof(tnid.szTip)/sizeof(wchar_t),L"%s - Winamp",WASABI_API_LNGSTRINGW(tips[i]));
+ else
+ FormCompactText(tnid.szTip,(sizeof(tnid.szTip)/sizeof(wchar_t)));
+
+ Shell_NotifyIcon(NIM_ADD, &tnid);
+ }
+ }
+ }
+}
+
+void config(void)
+{
+ if(!IsWindow(configwnd))
+ WASABI_API_DIALOGBOXW(IDD_DIALOG1,0,ConfigProc);
+ else
+ SetActiveWindow(configwnd);
+}
+
+void quit(void)
+{
+ config_enabled=0;
+ do_icons(0);
+ free_icons();
+}
+
+BOOL CALLBACK FindTrayWnd(HWND hwnd, LPARAM lParam)
+{
+ wchar_t szClassName[256] = {0};
+ GetClassName(hwnd, szClassName, 255); // Did we find the Main System Tray? If so, then get its size and quit
+ if (!lstrcmpi(szClassName, L"TrayNotifyWnd"))
+ {
+ HWND* pWnd = (HWND*)lParam;
+ *pWnd = hwnd;
+ return FALSE;
+ }
+
+ //Original code I found on Internet were seeking here for system clock and it was assumming that clock is on the right side of tray.
+ //After that calculated size of tray was adjusted by removing space occupied by clock.
+ //This is not a good idea - some clocks are ABOVE or somewhere else on the screen. I found that is far safer to just ignore clock space.
+ return TRUE;
+}
+
+BOOL CALLBACK FindToolBarInTrayWnd(HWND hwnd, LPARAM lParam)
+{
+ wchar_t szClassName[256] = {0};
+ GetClassName(hwnd, szClassName, 255); // Did we find the Main System Tray? If so, then get its size and quit
+ if (!lstrcmpi(szClassName, L"ToolbarWindow32"))
+ {
+ HWND* pWnd = (HWND*)lParam;
+ *pWnd = hwnd;
+ return FALSE;
+ }
+ return TRUE;
+}
+
+HWND GetTrayNotifyWnd(BOOL a_bSeekForEmbedToolbar)
+{
+ HWND hWndTrayNotifyWnd = 0, hWndShellTrayWnd = FindWindow(L"Shell_TrayWnd", 0);
+
+ if (hWndShellTrayWnd)
+ {
+ EnumChildWindows(hWndShellTrayWnd, FindTrayWnd, (LPARAM)&hWndTrayNotifyWnd);
+
+ if(hWndTrayNotifyWnd && IsWindow(hWndTrayNotifyWnd))
+ {
+ HWND hWndToolBarWnd = 0;
+ EnumChildWindows(hWndTrayNotifyWnd, FindToolBarInTrayWnd, (LPARAM)&hWndToolBarWnd);
+ if(hWndToolBarWnd)
+ {
+ return hWndToolBarWnd;
+ }
+ }
+
+ return hWndTrayNotifyWnd;
+ }
+
+ return hWndShellTrayWnd;
+}
+
+typedef BOOL (WINAPI *ISWOW64PROCESS)(HANDLE hProcess,PBOOL Wow64Process);
+BOOL IsRunningX64(void){
+ ISWOW64PROCESS iswow64process = (ISWOW64PROCESS)GetProcAddress(GetModuleHandle(L"kernel32"),"IsWow64Process");
+ if (iswow64process) {
+ BOOL Wow64Process = 0;
+ if(iswow64process(GetCurrentProcess(),&Wow64Process)){
+ return Wow64Process;
+ }
+ }
+ return FALSE;
+}
+
+struct TRAYDATA
+{
+ HWND hwnd;
+ UINT uID;
+ UINT uCallbackMessage;
+ DWORD Reserved[2];
+ HICON hIcon;
+};
+
+typedef struct _TBBUTTON64 {
+ int iBitmap;
+ int idCommand;
+ BYTE fsState;
+ BYTE fsStyle;
+ BYTE bReserved[6]; // padding for alignment
+ DWORD_PTR dwData;
+ INT_PTR iString;
+} TBBUTTON64, NEAR* PTBBUTTON64, *LPTBBUTTON64;
+typedef const TBBUTTON64 *LPCTBBUTTON64;
+
+// this is used on Win7+ installs where the OS has a direct api to allow for the querying of the icon position
+// most likely added natively due to the notification area fly out
+BOOL NotifyIconGetRect(LPRECT a_rcIcon){
+ if(g_Shell_NotifyIconGetRect){
+ NOTIFYICONIDENTIFIER niid = {sizeof(NOTIFYICONIDENTIFIER),plugin.hwndParent,SYSTRAY_ICON_BASE+5,0};
+ return SUCCEEDED(g_Shell_NotifyIconGetRect(&niid,a_rcIcon));
+ }
+ return FALSE;
+}
+
+//First tracking method: attaches to Tray process and reads data directly, is fast and reliable but will fail if user uses non standard tray software
+//It was suggested by Neal Andrews with VB example: http://www.codeproject.com/shell/ctrayiconposition.asp?select=999036&forumid=14631&df=100#xx999036xx
+//Ported to C++ by Ireneusz Zielinski
+//Made vaguely 64-bit compatible in v2.2 of this plugin
+BOOL FindOutPositionOfIconDirectly(HWND a_hWndOwner, const int a_iButtonID, LPRECT a_rcIcon)
+{
+ if(!NotifyIconGetRect(a_rcIcon))
+ {
+ DWORD dwTrayProcessID = -1, tbSize = (isX64?sizeof(TBBUTTON64):sizeof(TBBUTTON));
+ HANDLE hTrayProc = NULL;
+ int iButtonsCount = 0, iButton = 0;
+ LPVOID lpData = 0, lpData2 = 0;
+ BOOL bIconFound = FALSE;
+
+ //first of all let's find a Tool bar control embed in Tray window
+ HWND hWndTray = GetTrayNotifyWnd(TRUE);
+
+ if (hWndTray == NULL)
+ {
+ return FALSE;
+ }
+
+ //now we have to get an ID of the parent process for system tray
+ GetWindowThreadProcessId(hWndTray, &dwTrayProcessID);
+ if(!dwTrayProcessID)
+ {
+ return FALSE;
+ }
+
+ // need to use the older PROCESS_ALL_ACCESS define as it otherwise causes
+ // this to fail on all XP machines but will still work ok on Vista / Win7
+ #define PROCESS_ALL_ACCESS_XP (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFF)
+ hTrayProc = OpenProcess(PROCESS_ALL_ACCESS_XP/*PROCESS_ALL_ACCESS*/, 0, dwTrayProcessID);
+ if(hTrayProc == NULL)
+ {
+ return FALSE;
+ }
+
+ //now we check how many buttons is there - should be more than 0
+ iButtonsCount = (int)SendMessage(hWndTray, TB_BUTTONCOUNT, 0, 0);
+
+ //We want to get data from another process - it's not possible to just send messages like TB_GETBUTTON with a localy
+ //allocated buffer for return data. Pointer to localy allocated data has no usefull meaning in a context of another
+ //process (since Win95) - so we need to allocate some memory inside Tray process.
+ //We allocate sizeof(TBBUTTON) bytes of memory - because TBBUTTON is the biggest structure we will fetch. But this buffer
+ //will be also used to get smaller pieces of data like RECT structures.
+ lpData = VirtualAllocEx(hTrayProc, NULL, tbSize, MEM_COMMIT, PAGE_READWRITE);
+ if(lpData == NULL || iButtonsCount < 1)
+ {
+ CloseHandle(hTrayProc);
+ return FALSE;
+ }
+
+ for(iButton = 0; iButton < iButtonsCount; iButton++)
+ {
+ HWND hWndOfIconOwner = 0;
+ int iIconId = 0;
+
+ //first let's read TBUTTON information about each button in a task bar of tray
+ SIZE_T dwBytesRead = -1;
+ TBBUTTON64 buttonData64 = {0};
+ TBBUTTON buttonData = {0};
+ TRAYDATA traydata = {0};
+
+ SendMessage(hWndTray, TB_GETBUTTON, iButton, (LPARAM)lpData);
+ ReadProcessMemory(hTrayProc, lpData, (isX64?(LPVOID)&buttonData64:&buttonData), tbSize, &dwBytesRead);
+
+ if(dwBytesRead < tbSize)
+ {
+ continue;
+ }
+
+ // now let's read extra data associated with each button: there will be a HWND of the window that created an icon and icon ID
+ ReadProcessMemory(hTrayProc, (LPCVOID)(isX64?buttonData64.dwData:buttonData.dwData), (LPVOID)&traydata, sizeof(TRAYDATA), &dwBytesRead);
+ if(dwBytesRead < sizeof(TRAYDATA))
+ {
+ continue;
+ }
+
+ // will get the hwnd and icon id of the 'button' being checked factoring for x86 and x64 structures
+ if(!isX64)
+ {
+ hWndOfIconOwner = traydata.hwnd;
+ iIconId = traydata.uID;
+ }
+ else
+ {
+ LPARAM *tb = (LPARAM*)&traydata;
+ hWndOfIconOwner = (HWND)tb[0];
+ iIconId = (int)tb[2];
+ }
+
+ if(hWndOfIconOwner != a_hWndOwner || iIconId != a_iButtonID)
+ {
+ continue;
+ }
+
+ //we found our icon - in WinXP/Vista+ it could be hidden - let's check it:
+ if(buttonData.fsState & TBSTATE_HIDDEN)
+ {
+ break;
+ }
+
+ //now just ask a tool bar of rectangle of our icon
+ SendMessage(hWndTray, TB_GETITEMRECT, iButton, (LPARAM)lpData);
+ ReadProcessMemory(hTrayProc, lpData, a_rcIcon, sizeof(RECT), &dwBytesRead);
+
+ if(dwBytesRead < sizeof(RECT))
+ {
+ continue;
+ }
+
+ MapWindowPoints(hWndTray, NULL, (LPPOINT)a_rcIcon, 2);
+ bIconFound = TRUE;
+ break;
+ }
+
+ VirtualFreeEx(hTrayProc, lpData, 0, MEM_RELEASE);
+ VirtualFreeEx(hTrayProc, lpData2, 0, MEM_RELEASE);
+ CloseHandle(hTrayProc);
+
+ return bIconFound;
+ }
+ return TRUE;
+}
+
+HICON CreateInternalIcon(void)
+{
+ HICON hGrayIcon = 0;
+ HDC hMainDC = 0, hMemDC1 = 0, hMemDC2 = 0;
+ BITMAP bmp = {0};
+ ICONINFO csII = {0}, csGrayII = {0};
+
+ // destroy the old version of the icon where possible otherwise we'll get a resource leak
+ // which can have a nasty effect if allowed to grow too large
+ if(Icons[5]){
+ DestroyIcon(Icons[5]);
+ }
+
+ // create a dummy base icon with which to work on (saves having to bundle a blank on in the dll)
+ if(!dummyIcon){dummyIcon = CreateIcon(plugin.hDllInstance,32,32,1,32,0,0);}
+
+ if(!GetIconInfo(dummyIcon,&csII)){return 0;}
+
+ if(!(hMainDC = GetDC(plugin.hwndParent)) || !(hMemDC1 = CreateCompatibleDC(hMainDC)) || !(hMemDC2 = CreateCompatibleDC(hMainDC))){
+ return 0;
+ }
+
+ if(GetObject(csII.hbmColor,sizeof(BITMAP),&bmp))
+ {
+ int width = 0, height = 0;
+ csGrayII.hbmColor = CreateBitmap((width = csII.xHotspot*2),(height = csII.yHotspot*2),bmp.bmPlanes,bmp.bmBitsPixel,0);
+ if(csGrayII.hbmColor){
+ int is_playing = (int)SendMessage(plugin.hwndParent,WM_WA_IPC,0,IPC_ISPLAYING), dwLoopY = 0, dwLoopX = 0;
+ // this is used for the temporary bitmap where the mask is created for the transparency (magic pink fun)
+ HBITMAP hAndMask = CreateCompatibleBitmap(hMemDC2,width,height);
+ HDC hAndMaskDC = CreateCompatibleDC(hMemDC2);
+ SelectObject(hAndMaskDC,hAndMask);
+
+ HBITMAP hOldBmp1 = (HBITMAP)SelectObject(hMemDC1,csII.hbmColor);
+ HBITMAP hOldBmp2 = (HBITMAP)SelectObject(hMemDC2,csGrayII.hbmColor);
+
+ SetStretchBltMode(hMemDC2,COLORONCOLOR);
+
+ // play or pause or 'blank' image would go here
+ SelectObject(hMemDC1,compact);
+ // not the most elegant code but it'll correctly select the play/pause icon as needed based on
+ // the current playback state and it's flip play/pause state as appropriately
+ StretchBlt(hMemDC2,0,0,16,16,hMemDC1,(!is_playing?0:(is_playing!=1?(flip?32:0):32)),0,8,8,SRCCOPY);
+
+ // open or stop image would go here
+ StretchBlt(hMemDC2,16,0,16,16,hMemDC1,(!is_playing?8:40),0,8,8,SRCCOPY);
+
+ // previous track image
+ StretchBlt(hMemDC2,0,16,16,16,hMemDC1,16,0,8,8,SRCCOPY);
+
+ // next track image
+ StretchBlt(hMemDC2,16,16,16,16,hMemDC1,24,0,8,8,SRCCOPY);
+
+ // process the image now that we've generated it
+ for(dwLoopX=0;dwLoopX<width;++dwLoopX)
+ {
+ for(dwLoopY=0;dwLoopY<height;++dwLoopY)
+ {
+ COLORREF MainBitPixel = GetPixel(hMemDC2,dwLoopX,dwLoopY);
+ // checks for magic pink and then will remove it and clear/set the relevant areas in the image mask
+ if(MainBitPixel == 0xff00ff)
+ {
+ SetPixel(hAndMaskDC,dwLoopX,dwLoopY,RGB(255,255,255));
+ SetPixel(hMemDC2,dwLoopX,dwLoopY,RGB(0,0,0));
+ }
+ else
+ {
+ SetPixel(hAndMaskDC,dwLoopX,dwLoopY,RGB(0,0,0));
+ SetPixel(hMemDC2,dwLoopX,dwLoopY,MainBitPixel);
+ }
+ }
+ }
+
+ // set the mask for the transparent areas, etc
+ csGrayII.hbmMask = hAndMask;
+
+ DeleteDC(hAndMaskDC);
+
+ SelectObject(hMemDC1,hOldBmp1);
+ SelectObject(hMemDC2,hOldBmp2);
+
+ csGrayII.fIcon = 1;
+ hGrayIcon = CreateIconIndirect(&csGrayII);
+ DeleteObject(hAndMask);
+ }
+
+ DeleteObject(csGrayII.hbmColor);
+ DeleteObject(csGrayII.hbmMask);
+ }
+
+ DeleteObject(csII.hbmColor);
+ DeleteObject(csII.hbmMask);
+ DeleteDC(hMemDC1);
+ DeleteDC(hMemDC2);
+ ReleaseDC(plugin.hwndParent,hMainDC);
+ return hGrayIcon;
+}
+
+LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ // this will detect the start of playback and allow us to query for the new compact mode text
+ // done in 2.1+ to resolve issues with the compact mode text not updating correctly in all cases
+ if(lParam == IPC_PLAYING_FILE){
+ update_file=0;
+ }
+
+ if((lParam == IPC_CB_MISC && wParam == IPC_CB_MISC_STATUS)){
+ if (config_enabled & (1<<5)) {
+ NOTIFYICONDATAW tnid={0};
+ tnid.cbSize=sizeof(NOTIFYICONDATAW);
+ tnid.hWnd=plugin.hwndParent;
+ tnid.uID=1029;
+ tnid.uFlags=NIF_ICON|NIF_TIP;
+ tnid.hIcon=(Icons[5] = CreateInternalIcon());
+
+ // force an update if stopping and the playlist is clear
+ if(!SendMessage(hwnd,WM_WA_IPC,0,IPC_ISPLAYING)){
+ if(!SendMessage(hwnd,WM_WA_IPC,0,IPC_GETLISTLENGTH)){
+ file.filetitle[0] = 0;
+ update_file=0;
+ }
+ }
+
+ FormCompactText(tnid.szTip,(sizeof(tnid.szTip)/sizeof(wchar_t)));
+ Shell_NotifyIcon(NIM_MODIFY,&tnid);
+ }
+ }
+
+ if(message == WM_TIMER && wParam == 64){
+ if (config_enabled & (1<<5)) {
+ if(SendMessage(hwnd,WM_WA_IPC,0,IPC_ISPLAYING) == 3){
+ NOTIFYICONDATAW tnid={0};
+ tnid.cbSize=sizeof(NOTIFYICONDATAW);
+ flip = !flip;
+ tnid.hWnd=plugin.hwndParent;
+ tnid.uID=1029;
+ tnid.uFlags=NIF_ICON|NIF_TIP;
+ tnid.hIcon=(Icons[5] = CreateInternalIcon());
+ FormCompactText(tnid.szTip,(sizeof(tnid.szTip)/sizeof(wchar_t)));
+ Shell_NotifyIcon(NIM_MODIFY,&tnid);
+ }
+ else
+ {
+ NOTIFYICONDATAW tnid={0};
+ // this resets the play/pause flashing so it's in a known state when not paused
+ tnid.cbSize=sizeof(NOTIFYICONDATAW);
+ tnid.hWnd=plugin.hwndParent;
+ tnid.uID=1029;
+ tnid.uFlags=(flip?NIF_ICON:0)|NIF_TIP;
+ // only re-create the icon when it's needed to be done otherwise, just update the tooltip
+ if(flip)
+ {
+ tnid.hIcon=(Icons[5] = CreateInternalIcon());
+ }
+ flip = 0;
+ FormCompactText(tnid.szTip,sizeof(tnid.szTip)/sizeof(wchar_t));
+ Shell_NotifyIcon(NIM_MODIFY,&tnid);
+ }
+ }
+ }
+
+ if (message == WM_USER+2707)
+ {
+ switch (LOWORD(lParam))
+ {
+ case WM_LBUTTONDOWN:
+ if (config_enabled) switch (LOWORD(wParam))
+ {
+ // previous icon
+ case 1024:
+ {
+ int a;
+ if ((a= (int)SendMessage(hwnd,WM_USER,0,IPC_ISPLAYING)) == 0) // not playing, let's hit prev
+ {
+ SendMessage(hwnd,WM_COMMAND,WINAMP_BUTTON1,0);
+ }
+ else if (a != 3) // restart or full previous action
+ {
+ if ((GetKeyState(VK_CONTROL)&0x1000) && SendMessage(hwnd,WM_USER,0,IPC_GETOUTPUTTIME) > 2000 )
+ {
+ SendMessage(hwnd,WM_COMMAND,WINAMP_BUTTON2,0); // restart (only on a ctrl+click)
+ }
+ else
+ {
+ SendMessage(hwnd,WM_COMMAND,WINAMP_BUTTON1,0); // move to the previous track and then start
+ }
+ }
+ else
+ { // prev
+ SendMessage(hwnd,WM_COMMAND,WINAMP_BUTTON1,0);
+ }
+ }
+ return 0;
+
+ // play/pause icon
+ case 1025:
+ if ((GetKeyState(VK_CONTROL)&0x1000) ) // restart the current track
+ {
+ SendMessage(hwnd,WM_COMMAND,WINAMP_BUTTON4,0);
+ SendMessage(hwnd,WM_COMMAND,WINAMP_BUTTON2,0);
+ }
+ else
+ {
+ // do play/pause switching to maintain current usability of the plugin
+ SendMessage(hwnd,WM_COMMAND,WINAMP_BUTTON2+(SendMessage(hwnd,WM_USER,0,IPC_ISPLAYING) == 1),0);
+ }
+ return 0;
+
+ // stop icon
+ case 1026:
+ SendMessage(hwnd,WM_COMMAND,WINAMP_BUTTON4 + ((GetKeyState(VK_SHIFT) & 0x1000)?100:0) ,0);
+ return 0;
+
+ // next icon
+ case 1027:
+ SendMessage(hwnd,WM_COMMAND,WINAMP_BUTTON5,0);
+ return 0;
+
+ // open file(s) icon
+ case 1028:
+ SetForegroundWindow(hwnd);
+ if (GetKeyState(VK_CONTROL) & (1<<15))
+ SendMessage(hwnd,WM_COMMAND,WINAMP_FILE_LOC,0);
+ else if (GetKeyState(VK_SHIFT) & (1<<15))
+ SendMessage(hwnd,WM_COMMAND,WINAMP_FILE_DIR,0);
+ else
+ SendMessage(hwnd,WM_COMMAND,WINAMP_FILE_PLAY,0);
+ return 0;
+
+ // 4way mode handling, etc
+ case 1029:
+ {
+ RECT rc = {0}, r = {0};
+
+ // Note: this isn't compatible with hidden icons on Win7 (still to be fixed for v2.4)
+ if(FindOutPositionOfIconDirectly(hwnd,1029,&rc))
+ {
+ int i = 0,
+ // on at least Win7 (possibly earlier) the icon size is different than a fixed size
+ // so for v2.3 we're just going to split the icon based on the reported size rather
+ // than assuming it is a 16x16 (really 18x18 icon) as Win7's taskbar is different!
+ height = (rc.bottom-rc.top)/2,
+ width = (rc.right-rc.left)/2,
+ x[4] = {0,width,0,width},
+ y[4] = {0,0,height,height};
+ POINT pt = {0};
+ GetCursorPos(&pt);
+ for(i = 0; i < 4; i++)
+ {
+ CopyRect(&r,&rc);
+ r.right = r.left+x[i]+width;
+ r.bottom = r.top+y[i]+height;
+
+ if(PtInRect(&r,pt))
+ {
+ switch(i)
+ {
+ // play/pause icon
+ case 0:
+ if ((GetKeyState(VK_CONTROL)&0x1000) ) // restart the current track
+ {
+ SendMessage(hwnd,WM_COMMAND,WINAMP_BUTTON4,0);
+ SendMessage(hwnd,WM_COMMAND,WINAMP_BUTTON2,0);
+ }
+ else
+ {
+ // do play/pause switching to maintain current usability of the plugin
+ SendMessage(hwnd,WM_COMMAND,WINAMP_BUTTON2+(SendMessage(hwnd,WM_USER,0,IPC_ISPLAYING) == 1),0);
+ }
+ break;
+
+ // open file(s) / stop icon
+ case 1:
+ if(!SendMessage(hwnd,WM_USER,0,IPC_ISPLAYING)){
+ SetForegroundWindow(hwnd);
+ if (GetKeyState(VK_CONTROL) & (1<<15))
+ SendMessage(hwnd,WM_COMMAND,WINAMP_FILE_LOC,0);
+ else if (GetKeyState(VK_SHIFT) & (1<<15))
+ SendMessage(hwnd,WM_COMMAND,WINAMP_FILE_DIR,0);
+ else
+ SendMessage(hwnd,WM_COMMAND,WINAMP_FILE_PLAY,0);
+ }
+ else{
+ SendMessage(hwnd,WM_COMMAND,WINAMP_BUTTON4 + ((GetKeyState(VK_SHIFT) & 0x1000)?100:0) ,0);
+ }
+ break;
+
+ // previous icon
+ case 2:
+ {
+ int a;
+ if ((a= (int)SendMessage(hwnd,WM_USER,0,IPC_ISPLAYING)) == 0) // not playing, let's hit prev
+ {
+ SendMessage(hwnd,WM_COMMAND,WINAMP_BUTTON1,0);
+ }
+ else if (a != 3) // restart or full previous action
+ {
+ if ((GetKeyState(VK_CONTROL)&0x1000) && SendMessage(hwnd,WM_USER,0,IPC_GETOUTPUTTIME) > 2000 )
+ {
+ SendMessage(hwnd,WM_COMMAND,WINAMP_BUTTON2,0); // restart (only on a ctrl+click)
+ }
+ else
+ {
+ SendMessage(hwnd,WM_COMMAND,WINAMP_BUTTON1,0); // move to the previous track and then start
+ }
+ }
+ else
+ { // prev
+ SendMessage(hwnd,WM_COMMAND,WINAMP_BUTTON1,0);
+ }
+ }
+ break;
+
+ // next icon
+ case 3:
+ SendMessage(hwnd,WM_COMMAND,WINAMP_BUTTON5,0);
+ break;
+ }
+ break;
+ }
+ }
+ }
+ }
+ return 0;
+
+ // vol down
+ case 1030:
+ {
+ int curvol = (int)SendMessage(hwnd,WM_WA_IPC,-666,IPC_SETVOLUME)-((GetKeyState(VK_CONTROL)&0x1000)?30:10);
+ if(curvol<0){curvol = 0;}
+ SendMessage(hwnd,WM_WA_IPC,curvol,IPC_SETVOLUME);
+ }
+ return 0;
+
+ // vol up
+ case 1031:
+ {
+ int curvol = (int)SendMessage(hwnd,WM_WA_IPC,-666,IPC_SETVOLUME)+((GetKeyState(VK_CONTROL)&0x1000)?30:10);
+ if(curvol>255){curvol = 255;}
+ SendMessage(hwnd,WM_WA_IPC,curvol,IPC_SETVOLUME);
+ }
+ return 0;
+ }
+ break;
+
+ case WM_RBUTTONDOWN:
+ if (config_enabled) switch (LOWORD(wParam))
+ {
+ // previousicon
+ case 1024:
+ {
+ SendMessage(hwnd,WM_COMMAND,WINAMP_BUTTON5,0);
+ }
+ break;
+
+ // next icon
+ case 1027:
+ {
+ int a;
+ if ((a= (int)SendMessage(hwnd,WM_USER,0,IPC_ISPLAYING)) == 0) // not playing, let's hit prev
+ {
+ SendMessage(hwnd,WM_COMMAND,WINAMP_BUTTON1,0);
+ }
+ else if (a != 3) // restart or full previous action
+ {
+ if ((GetKeyState(VK_CONTROL)&0x1000) && SendMessage(hwnd,WM_USER,0,IPC_GETOUTPUTTIME) > 2000 )
+ {
+ SendMessage(hwnd,WM_COMMAND,WINAMP_BUTTON2,0); // restart (only on a ctrl+click)
+ }
+ else
+ {
+ SendMessage(hwnd,WM_COMMAND,WINAMP_BUTTON1,0); // move to the previous track and then start
+ SendMessage(hwnd,WM_COMMAND,WINAMP_BUTTON2,0);
+ }
+ }
+ else
+ { // prev
+ SendMessage(hwnd,WM_COMMAND,WINAMP_BUTTON1,0);
+ }
+ }
+ break;
+
+ // vol down
+ case 1031:
+ {
+ int curvol = (int)SendMessage(hwnd,WM_WA_IPC,-666,IPC_SETVOLUME)-((GetKeyState(VK_CONTROL)&0x1000)?30:10);
+ if(curvol<0){curvol = 0;}
+ SendMessage(hwnd,WM_WA_IPC,curvol,IPC_SETVOLUME);
+ }
+ return 0;
+
+ // vol up
+ case 1030:
+ {
+ int curvol = (int)SendMessage(hwnd,WM_WA_IPC,-666,IPC_SETVOLUME)+((GetKeyState(VK_CONTROL)&0x1000)?30:10);
+ if(curvol>255){curvol = 255;}
+ SendMessage(hwnd,WM_WA_IPC,curvol,IPC_SETVOLUME);
+ }
+ return 0;
+ }
+ break;
+ }
+ }
+
+ {
+ int ret = (int)CallWindowProc(lpWndProcOld,hwnd,message,wParam,lParam);
+
+ // do this after passing the main batch of messages onto Winamp/rest of the subclass chain so
+ // that Winamp will restore its tray icon first and then we do ours (otherwise it looks silly)
+ if(message == s_uTaskbarRestart)
+ {
+ // have to force the icons to be displayed since there are none in the tray at this point
+ do_icons(1);
+ }
+
+ return ret;
+ }
+}
+
+// GetWindowsVersionRunningOnCompact(...)
+//
+// Function to get the version of windows being run on
+//
+// Optionally a 'short version[2]' can be passed into the
+// function as 'GetWindowsVersionRunningOnCompact(version)'
+// which allows the OS version to be returned for the user to
+// be able to make use of
+//
+int GetWindowsVersionRunningOnCompact(DWORD* version)
+{
+ OSVERSIONINFO osvi = {sizeof(OSVERSIONINFO),0};
+ int ver_detect = -1;
+
+ // Win9x detection
+ //
+ // Windows 95 - Major 4 & Minor 0 ver_detect = 1
+ // Windows 98 - Major 4 & Minor 10 ver_detect = 2
+ // Windows ME - Major 4 & Minor 90 ver_detect = 3
+ //
+ // Win NT detection
+ //
+ // Windows NT 3.51 - Major 3 & Minor 51 ver_detect = 4
+ // Windows NT 4 - Major 4 & Minor 0 ver_detect = 5
+ // Windows 2000 - Major 5 & Minor 0 ver_detect = 6
+ // Windows XP - Major 5 & Minor 1 ver_detect = 7
+ // Windows Server 2003 - Major 5 & Minor 2 ver_detect = 8
+ // Windows Vista - Major 6 & Minor 0 ver_detect = 9
+ // Windows 7 - Major 6 & Minor 1 ver_detect = 9
+ // Windows 8 - Major 6 & Minor 2 ver_detect = 9
+ // Windows 8.1 - Major 6 & Minor 3 ver_detect = 9
+ // Windows 10 - Major 10 & Minor 0 ver_detect = 10
+ // Windows 11 - Major 11 & Minor 0 ver_detect = 11
+ //
+ // Unknown OS version ver_detect = -1
+
+ GetVersionEx(&osvi);
+
+ // is it a Win9x platform that we are running on?
+ if(osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
+ {
+ // Windows 98 (4.10)
+ if(osvi.dwMinorVersion == 10){
+ ver_detect = 2;
+ }
+
+ // Windows ME (4.90)
+ else if(osvi.dwMinorVersion == 90){
+ ver_detect = 3;
+ }
+
+ // Windows 95 (4.0)
+ else {
+ ver_detect = 1;
+ }
+ }
+
+ // is it a WinNT platform that we are running on?
+ else if(osvi.dwPlatformId == VER_PLATFORM_WIN32_NT)
+ {
+ // Windows NT 4 (4.0)
+ if(osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0)
+ {
+ ver_detect = 5;
+ }
+
+ else if(osvi.dwMajorVersion == 5)
+ {
+ // Windows XP (5.1)
+ if(osvi.dwMinorVersion == 1)
+ {
+ ver_detect = 7;
+ }
+
+ // Windows Server 2003 (5.2)
+ else if(osvi.dwMinorVersion == 2)
+ {
+ ver_detect = 8;
+ }
+
+ // Windows 2000 (5.0)
+ else
+ {
+ ver_detect = 6;
+ }
+ }
+
+ // Windows Vista/7/8/8.1 (6.0)
+ else if(osvi.dwMajorVersion == 6)
+ {
+ ver_detect = 9;
+ }
+
+ // Windows 10 (10.0)
+ else if(osvi.dwMajorVersion == 10)
+ {
+ ver_detect = 10;
+ }
+
+ // Windows 11 (11.0)
+ else if(osvi.dwMajorVersion == 11)
+ {
+ ver_detect = 11;
+ }
+
+ // Windows NT 3.51 (3.51)
+ else
+ {
+ ver_detect = 4;
+ }
+ }
+ else
+ {
+ ver_detect = -1;
+ }
+
+ // copies the value into the structure
+ if(version)
+ {
+ *version = MAKELONG(osvi.dwMinorVersion,osvi.dwMajorVersion);
+ }
+
+ return ver_detect;
+}
+
+void GetWinampPath(void)
+{
+ wchar_t* p = wa_path;
+ p += GetModuleFileName(0,wa_path,ARRAYSIZE(wa_path)) - 1;
+ while(p && *p && *p != L'\\'){p = CharPrev(wa_path,p);}
+ if (p) *p = 0;
+}
+
+int init(void)
+{
+ // loader so that we can get the localisation service api for use
+ WASABI_API_SVC = (api_service*)SendMessage(plugin.hwndParent, WM_WA_IPC, 0, IPC_GET_API_SERVICE);
+ if (WASABI_API_SVC == (api_service*)1) WASABI_API_SVC = NULL;
+ if (!WASABI_API_SVC || WASABI_API_SVC == (api_service *)1)
+ return GEN_INIT_FAILURE;
+
+ xporhigher = ((winver=GetWindowsVersionRunningOnCompact(0))>6);
+ isX64 = IsRunningX64();
+ s_uTaskbarRestart = RegisterWindowMessage(TEXT("TaskbarCreated"));
+ g_Shell_NotifyIconGetRect = (SHELL_NOTIFYICONGETRECT)GetProcAddress(GetModuleHandle(L"SHELL32"),"Shell_NotifyIconGetRect");
+
+ waServiceFactory *sf = WASABI_API_SVC->service_getServiceByGuid(languageApiGUID);
+ if (sf) WASABI_API_LNG = reinterpret_cast<api_language*>(sf->getInterface());
+
+ // need to have this initialised before we try to do anything with localisation features
+ WASABI_API_START_LANG(plugin.hDllInstance,GenTrayLangGUID);
+
+ StringCchPrintf(szDescription, ARRAYSIZE(szDescription),
+ WASABI_API_LNGSTRINGW(IDS_NULLSOFT_TRAY_CONTROL), PLUGIN_VERSION);
+ plugin.description = (char*)szDescription;
+
+ GetWinampPath();
+ config_read();
+
+ if (IsWindowUnicode(plugin.hwndParent))
+ lpWndProcOld = (WNDPROC)SetWindowLongPtrW(plugin.hwndParent,GWLP_WNDPROC,(LPARAM)WndProc);
+ else
+ lpWndProcOld = (WNDPROC)SetWindowLongPtrA(plugin.hwndParent,GWLP_WNDPROC,(LPARAM)WndProc);
+
+ do_icons(0);
+
+ return 0;
+}
+
+static HCURSOR link_hand_cursor;
+LRESULT link_handlecursor(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ LRESULT ret = CallWindowProcW((WNDPROC)GetPropW(hwndDlg, L"link_proc"), hwndDlg, uMsg, wParam, lParam);
+ // override the normal cursor behaviour so we have a hand to show it is a link
+ if(uMsg == WM_SETCURSOR)
+ {
+ if((HWND)wParam == hwndDlg)
+ {
+ if(!link_hand_cursor)
+ {
+ link_hand_cursor = LoadCursor(NULL, IDC_HAND);
+ }
+ SetCursor(link_hand_cursor);
+ return TRUE;
+ }
+ }
+ return ret;
+}
+
+void link_startsubclass(HWND hwndDlg, UINT id){
+HWND ctrl = GetDlgItem(hwndDlg, id);
+ if(!GetPropW(ctrl, L"link_proc"))
+ {
+ SetPropW(ctrl, L"link_proc",
+ (HANDLE)SetWindowLongPtrW(ctrl, GWLP_WNDPROC, (LONG_PTR)link_handlecursor));
+ }
+}
+
+BOOL CALLBACK ConfigProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)
+{
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ int count = CB_ERR;
+ configwnd = hwndDlg;
+ dlg_init = 1;
+ link_startsubclass(hwndDlg,IDC_LINK);
+
+ CheckDlgButton(hwndDlg,IDC_ONOFF,on?BST_CHECKED:BST_UNCHECKED);
+
+ for (int i = 0; i < NUM_ICONS; i++)
+ {
+ wchar_t str[512] = {0}, tmp[256] = {0}, tmp2[256] = {0};
+ CheckDlgButton(hwndDlg,IDC_PREV+i,(config_enabled&(1<<i))?BST_CHECKED:BST_UNCHECKED);
+ StringCchPrintf(str,512,L"%s %s",
+ WASABI_API_LNGSTRINGW_BUF(tips[i],tmp2,256),
+ (tips_ex[i]!=-1?WASABI_API_LNGSTRINGW_BUF(tips_ex[i],tmp,256):L""));
+ SetDlgItemText(hwndDlg,IDC_PREV+i,str);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_PREV+i),on);
+ }
+
+ EnableWindow(GetDlgItem(hwndDlg,IDC_COMBO2),on);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_BUTTON1),custom_enabled && on);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_EDIT1),custom_enabled && on);
+
+ SetDlgItemText(hwndDlg,IDC_EDIT1,ico_pack_safe);
+
+ dlg_init = 0;
+
+ WIN32_FIND_DATA findfile = {0};
+ wchar_t use[MAX_PATH] = {0};
+
+ StringCchPrintf(use,MAX_PATH,L"%s\\Plugins\\Tray_Control\\*.*",wa_path);
+ HANDLE hFind = FindFirstFile(use, &findfile);
+
+ while(hFind && hFind != INVALID_HANDLE_VALUE)
+ {
+ if(findfile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY){
+ WIN32_FIND_DATA subfile = {0};
+ StringCchPrintf(use,MAX_PATH,L"%s\\Plugins\\Tray_Control\\%s\\*.icp",
+ wa_path,findfile.cFileName,findfile.cFileName);
+
+ HANDLE hsubFind = FindFirstFile(use,&subfile);
+
+ while(hsubFind && hsubFind != INVALID_HANDLE_VALUE){
+ wchar_t icpname[MAX_PATH] = {0};
+ StringCchPrintf(icpname,MAX_PATH,
+ L"%s\\Plugins\\Tray_Control\\%s\\%s",
+ wa_path,findfile.cFileName,subfile.cFileName);
+
+ if(PathFileExists(icpname))
+ {
+ // need to ideally make this one work with CharPrev(..)
+ wchar_t* p = subfile.cFileName + lstrlen(subfile.cFileName) - 1;
+ while(p && *p && *p != L'.'){p = CharPrevW(subfile.cFileName, p);}
+ if (p) *p = 0;
+ if(!lstrcmpiW(findfile.cFileName,subfile.cFileName))
+ {
+ SendDlgItemMessageW(hwndDlg,IDC_COMBO2,CB_ADDSTRING,0,(LPARAM)subfile.cFileName);
+ }
+ else
+ {
+ wchar_t str[MAX_PATH] = {0};
+ int insertpos = 0;
+ StringCchPrintf(str,MAX_PATH,L"%s\\%s",findfile.cFileName,subfile.cFileName);
+ insertpos = (int)SendDlgItemMessage(hwndDlg,IDC_COMBO2,CB_ADDSTRING,0,(LPARAM)str);
+ if(insertpos != CB_ERR)
+ {
+ SendDlgItemMessage(hwndDlg,IDC_COMBO2,CB_SETITEMDATA,insertpos,1);
+ }
+ }
+ }
+
+ // if there are no more files then stop the search
+ if(hsubFind && !FindNextFile(hsubFind, &subfile))
+ {
+ FindClose(hsubFind);
+ hsubFind = 0;
+ }
+ }
+ }
+
+ // if there are no more files then stop the search
+ if(hFind && !FindNextFileW(hFind, &findfile))
+ {
+ FindClose(hFind);
+ hFind = 0;
+ }
+ }
+
+ EnableWindow(GetDlgItem(hwndDlg,IDC_EDIT1),custom_enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_BUTTON1),custom_enabled);
+
+ EnableWindow(GetDlgItem(hwndDlg,IDC_PREV6),winver>=6 && on);
+
+ SendDlgItemMessage(hwndDlg,IDC_COMBO2,CB_INSERTSTRING,0,
+ (LPARAM)WASABI_API_LNGSTRINGW(IDS_DEFAULT_ICONS));
+ SendDlgItemMessage(hwndDlg,IDC_COMBO2,CB_INSERTSTRING,
+ (count = (int)SendDlgItemMessage(hwndDlg,IDC_COMBO2,CB_GETCOUNT,0,0)),
+ (LPARAM)WASABI_API_LNGSTRINGW(IDS_CUSTOM_ICON_PACK));
+
+ if (!custom_enabled)
+ {
+ if(ico_pack[0])
+ {
+ wchar_t base[MAX_PATH] = {0}, *pack = 0, use[MAX_PATH] = {0};
+ StringCchPrintf(use,MAX_PATH,L"%s\\Plugins\\Tray_Control\\",wa_path);
+ lstrcpyn(base,ico_pack,ARRAYSIZE(base));
+
+ if(StrStrI(base,use))
+ {
+ pack = PathFindFileName(base);
+ if (pack && *pack)
+ {
+ PathRemoveExtension(pack);
+ }
+ }
+
+ count = (int)SendDlgItemMessage(hwndDlg,IDC_COMBO2,CB_FINDSTRINGEXACT,0,(LPARAM)pack);
+ if(count == CB_ERR)
+ {
+ count = 0;
+ }
+ }
+ else
+ {
+ count = 0;
+ }
+ }
+
+ SendDlgItemMessage(hwndDlg,IDC_COMBO2,CB_SETCURSEL,count,0);
+ SetFocus(GetDlgItem(hwndDlg,IDC_COMBO2));
+ }
+ break;
+
+ // mimicks the get... links in the winamp preferences
+ case WM_DRAWITEM:
+ {
+ DRAWITEMSTRUCT* lpdis = (DRAWITEMSTRUCT*)lParam;
+ if(lpdis->CtlID == IDC_LINK)
+ {
+ HFONT OldFont = 0;
+ LOGFONT lf = {0};
+ RECT rc = lpdis->rcItem, r = {0};
+ POINT pt = {0};
+ int in = 0;
+ wchar_t gicpStr[128] = {0};
+
+ WASABI_API_LNGSTRINGW_BUF(IDS_GET_ICON_PACKS,gicpStr,128);
+ GetObject(GetCurrentObject(lpdis->hDC,OBJ_FONT),sizeof(lf),&lf);
+ lf.lfUnderline = TRUE;
+ OldFont = (HFONT)SelectObject(lpdis->hDC,CreateFontIndirect(&lf));
+
+ // Calculate needed size of the control
+ DrawText(lpdis->hDC,gicpStr,-1,&rc,DT_VCENTER|DT_SINGLELINE|DT_CALCRECT);
+
+ // Make some more room so the focus rect won't cut letters off
+ rc.right = min(rc.right + 2, lpdis->rcItem.right);
+
+ GetWindowRect(lpdis->hwndItem,&r);
+ GetCursorPos(&pt);
+ in = PtInRect(&r,pt);
+ SetTextColor(lpdis->hDC,(COLORREF)RGB((in?255:0),0,(!in?255:0)));
+
+ // Draw the text
+ DrawText(lpdis->hDC,gicpStr,-1,&rc,DT_CENTER|DT_VCENTER|DT_SINGLELINE);
+
+ DeleteObject(SelectObject(lpdis->hDC, OldFont));
+ }
+ }
+ break;
+
+ case WM_COMMAND:
+ if (LOWORD(wParam) >= IDC_PREV && LOWORD(wParam) <= IDC_PREV+NUM_ICONS)
+ {
+ config_enabled=0;
+ for (int i = 0; i < NUM_ICONS; i++)
+ if (IsDlgButtonChecked(hwndDlg,IDC_PREV+i))
+ config_enabled |= 1<<i;
+ do_icons(0);
+ }
+
+ else if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
+ {
+ GetDlgItemText(hwndDlg,IDC_EDIT1,ico_pack_safe,ARRAYSIZE(ico_pack_safe));
+ config_write();
+ EndDialog(hwndDlg,0);
+ configwnd = 0;
+ }
+
+ else if (LOWORD(wParam) == IDC_ONOFF)
+ {
+ on = (IsDlgButtonChecked(hwndDlg,LOWORD(wParam))==BST_CHECKED);
+ for (int i = 0; i < NUM_ICONS; i++)
+ {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_PREV+i),on);
+ }
+ EnableWindow(GetDlgItem(hwndDlg,IDC_PREV6),winver>=6 && on);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_COMBO2),on);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_BUTTON1),custom_enabled && on);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_EDIT1),custom_enabled && on);
+
+ do_icons(1);
+ }
+
+ else if (LOWORD(wParam) == ID_INFO)
+ {
+ wchar_t str[2560] = {0}, str1[2048] = {0};
+ StringCchPrintf(str, 2560, WASABI_API_LNGSTRINGW_BUF(IDS_CONFIG_INFO, str1, 2048), wa_path);
+ MessageBoxW(hwndDlg,str,szDescription,0);
+ }
+
+ else if (LOWORD(wParam) == IDC_LINK && HIWORD(wParam) == BN_CLICKED)
+ {
+ SendMessage(plugin.hwndParent,WM_WA_IPC,(WPARAM)"https://winampheritage.com/plugin/nullsoft-tray-control-plug-in-icon-pack/222396",IPC_OPEN_URL);
+ }
+
+ else if (LOWORD(wParam) == IDC_BUTTON1)
+ {
+ OPENFILENAME of = {sizeof(OPENFILENAME),0};
+ wchar_t titleStr[128], filterStr[128] = {0};
+
+ of.hwndOwner = hwndDlg;
+ of.hInstance = plugin.hDllInstance;
+ of.lpstrFilter = WASABI_API_LNGSTRINGW_BUF(IDS_OFD_FILTER_STR,filterStr,128);
+ StringCchCat(filterStr+lstrlen(filterStr)+1,128,L"*.icp");
+ of.nMaxCustFilter = 64;
+ of.lpstrFile = ico_pack;
+ of.nMaxFile = ARRAYSIZE(ico_pack);
+ of.lpstrTitle = WASABI_API_LNGSTRINGW_BUF(IDS_OFD_TITLE_STR,titleStr,128);
+ of.nMaxFileTitle = lstrlen(of.lpstrTitle);
+ of.Flags = OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT|OFN_EXPLORER|OFN_PATHMUSTEXIST|OFN_CREATEPROMPT|OFN_ENABLESIZING|OFN_ALLOWMULTISELECT;
+ of.lpstrDefExt = L"icp";
+
+ if(GetOpenFileName(&of))
+ {
+ SetDlgItemText(hwndDlg,IDC_EDIT1,ico_pack);
+ do_icons(1);
+ }
+ }
+
+ else if (LOWORD(wParam) == IDC_EDIT1 && HIWORD(wParam)==EN_CHANGE)
+ {
+ if(!dlg_init)
+ {
+ GetDlgItemText(hwndDlg,IDC_EDIT1,ico_pack,ARRAYSIZE(ico_pack));
+ do_icons(1);
+ }
+ }
+
+ else if (LOWORD(wParam) == IDC_COMBO2 && HIWORD(wParam)== CBN_SELCHANGE)
+ {
+ wchar_t buf[MAX_PATH] = {0};
+ int cursel = (int)SendDlgItemMessage(hwndDlg,IDC_COMBO2,CB_GETCURSEL,0,0);
+ SendDlgItemMessage(hwndDlg,IDC_COMBO2,CB_GETLBTEXT,cursel,(LPARAM)buf);
+
+ custom_enabled=0;
+
+ if(cursel && cursel != CB_ERR)
+ {
+ if(cursel != (SendDlgItemMessage(hwndDlg,IDC_COMBO2,CB_GETCOUNT,0,0)-1))
+ {
+ // this will detect if it was a multi-entry style icon pack and form as required
+ if(!SendDlgItemMessage(hwndDlg,IDC_COMBO2,CB_GETITEMDATA,cursel,0))
+ {
+ StringCchPrintf(ico_pack,MAX_PATH,L"%s\\Plugins\\Tray_Control\\%s\\%s.icp",wa_path,buf,buf);
+ }
+ else
+ {
+ StringCchPrintf(ico_pack,MAX_PATH,L"%s\\Plugins\\Tray_Control\\%s.icp",wa_path,buf);
+ }
+ }
+ else
+ {
+ custom_enabled=1;
+ GetDlgItemText(hwndDlg,IDC_EDIT1,ico_pack,ARRAYSIZE(ico_pack));
+ }
+ }
+ else
+ {
+ ico_pack[0] = 0;
+ }
+
+ EnableWindow(GetDlgItem(hwndDlg,IDC_EDIT1),custom_enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_BUTTON1),custom_enabled);
+
+ do_icons(1);
+ }
+ break;
+ }
+ return FALSE;
+}
+
+void config_read(void)
+{
+ // this will only correctly work with Winamp 2.9+/5.x+
+ // see IPC_GETINIFILE for a way to query the location of Winamp.ini correctly
+ // whatever version of Winamp is being run on
+ // as of v2.41 this now uses IPC_GETINIFILEW though it's trivial to use
+ // IPC_GETINIFILE as a fallback on older clients (built for 5.58+)
+ ini_file=(wchar_t*)SendMessage(plugin.hwndParent,WM_USER,0,IPC_GETINIFILEW);
+ config_enabled = GetPrivateProfileInt(PLUGIN_NAME,L"BEN",config_enabled,ini_file);
+ custom_enabled = GetPrivateProfileInt(PLUGIN_NAME,L"custom",custom_enabled,ini_file);
+ on = GetPrivateProfileInt(PLUGIN_NAME,L"on",on,ini_file);
+ GetPrivateProfileString(PLUGIN_NAME,L"ico_pack",ico_pack,ico_pack,ARRAYSIZE(ico_pack),ini_file);
+ GetPrivateProfileString(PLUGIN_NAME,L"ico_pack_safe",ico_pack_safe,ico_pack_safe,ARRAYSIZE(ico_pack_safe),ini_file);
+}
+
+void config_write(void)
+{
+ if(!no_uninstall) return;
+
+ wchar_t string[32] = {0};
+ StringCchPrintf(string,32,L"%d",config_enabled);
+ WritePrivateProfileString(PLUGIN_NAME,L"BEN",string,ini_file);
+ WritePrivateProfileString(PLUGIN_NAME,L"ico_pack",ico_pack,ini_file);
+ WritePrivateProfileString(PLUGIN_NAME,L"ico_pack_safe",ico_pack_safe,ini_file);
+ StringCchPrintf(string,32,L"%d",custom_enabled);
+ WritePrivateProfileString(PLUGIN_NAME,L"custom",string,ini_file);
+ StringCchPrintf(string,32,L"%d",on);
+ WritePrivateProfileString(PLUGIN_NAME,L"on",string,ini_file);
+}
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ __declspec(dllexport) int winampUninstallPlugin(HINSTANCE hDllInst, HWND hwndDlg, int param){
+ // prompt to remove our settings with default as no (just incase)
+ if(MessageBoxW(hwndDlg,WASABI_API_LNGSTRINGW(IDS_DO_YOU_ALSO_WANT_TO_REMOVE_SETTINGS),
+ szDescription,MB_YESNO|MB_DEFBUTTON2) == IDYES)
+ {
+ WritePrivateProfileString(PLUGIN_NAME,0,0,ini_file);
+ no_uninstall = 0;
+ }
+
+ // as we're doing too much in subclasses, etc we cannot allow for on-the-fly removal so need to do a normal reboot
+ return GEN_PLUGIN_UNINSTALL_REBOOT;
+ }
+
+#ifdef __cplusplus
+}
+#endif \ No newline at end of file
diff --git a/Src/Plugins/General/gen_tray/WINAMPCMD.H b/Src/Plugins/General/gen_tray/WINAMPCMD.H
new file mode 100644
index 00000000..068b55ce
--- /dev/null
+++ b/Src/Plugins/General/gen_tray/WINAMPCMD.H
@@ -0,0 +1,62 @@
+#define WINAMP_FILE_QUIT 40001
+#define WINAMP_OPTIONS_PREFS 40012
+#define WINAMP_OPTIONS_AOT 40019
+#define WINAMP_FILE_REPEAT 40022
+#define WINAMP_FILE_SHUFFLE 40023
+#define WINAMP_HIGH_PRIORITY 40025
+#define WINAMP_FILE_PLAY 40029
+#define WINAMP_OPTIONS_EQ 40036
+#define WINAMP_OPTIONS_ELAPSED 40037
+#define WINAMP_OPTIONS_REMAINING 40038
+#define WINAMP_OPTIONS_PLEDIT 40040
+#define WINAMP_HELP_ABOUT 40041
+#define WINAMP_MAINMENU 40043
+#define WINAMP_BUTTON1 40044
+#define WINAMP_BUTTON2 40045
+#define WINAMP_BUTTON3 40046
+#define WINAMP_BUTTON4 40047
+#define WINAMP_BUTTON5 40048
+#define WINAMP_VOLUMEUP 40058
+#define WINAMP_VOLUMEDOWN 40059
+#define WINAMP_FFWD5S 40060
+#define WINAMP_REW5S 40061
+#define WINAMP_NEXT_WINDOW 40063
+#define WINAMP_OPTIONS_WINDOWSHADE 40064
+#define WINAMP_BUTTON1_SHIFT 40144
+#define WINAMP_BUTTON2_SHIFT 40145
+#define WINAMP_BUTTON3_SHIFT 40146
+#define WINAMP_BUTTON4_SHIFT 40147
+#define WINAMP_BUTTON5_SHIFT 40148
+#define WINAMP_BUTTON1_CTRL 40154
+#define WINAMP_BUTTON2_CTRL 40155
+#define WINAMP_BUTTON3_CTRL 40156
+#define WINAMP_BUTTON4_CTRL 40157
+#define WINAMP_BUTTON5_CTRL 40158
+#define WINAMP_OPTIONS_DSIZE 40165
+#define IDC_SORT_FILENAME 40166
+#define IDC_SORT_FILETITLE 40167
+#define IDC_SORT_ENTIREFILENAME 40168
+#define IDC_SELECTALL 40169
+#define IDC_SELECTNONE 40170
+#define IDC_SELECTINV 40171
+#define IDM_EQ_LOADPRE 40172
+#define IDM_EQ_LOADMP3 40173
+#define IDM_EQ_LOADDEFAULT 40174
+#define IDM_EQ_SAVEPRE 40175
+#define IDM_EQ_SAVEMP3 40176
+#define IDM_EQ_SAVEDEFAULT 40177
+#define IDM_EQ_DELPRE 40178
+#define IDM_EQ_DELMP3 40180
+#define IDC_PLAYLIST_PLAY 40184
+#define WINAMP_FILE_LOC 40185
+#define WINAMP_OPTIONS_EASYMOVE 40186
+#define WINAMP_FILE_DIR 40187
+#define WINAMP_EDIT_ID3 40188
+#define WINAMP_TOGGLE_AUTOSCROLL 40189
+#define WINAMP_VISSETUP 40190
+#define WINAMP_PLGSETUP 40191
+#define WINAMP_VISPLUGIN 40192
+#define WINAMP_JUMP 40193
+#define WINAMP_JUMPFILE 40194
+#define WINAMP_JUMP10FWD 40195
+#define WINAMP_JUMP10BACK 40197
diff --git a/Src/Plugins/General/gen_tray/api__gen_tray.h b/Src/Plugins/General/gen_tray/api__gen_tray.h
new file mode 100644
index 00000000..d50e2c43
--- /dev/null
+++ b/Src/Plugins/General/gen_tray/api__gen_tray.h
@@ -0,0 +1,8 @@
+#ifndef NULLSOFT_GEN_TRAY_API_H
+#define NULLSOFT_GEN_TRAY_API_H
+
+#include "api/service/api_service.h"
+#include "api/service/waServiceFactory.h"
+#include "../Agave/Language/api_language.h"
+
+#endif // !NULLSOFT_GEN_TRAY_API_H \ No newline at end of file
diff --git a/Src/Plugins/General/gen_tray/gen_tray.rc b/Src/Plugins/General/gen_tray/gen_tray.rc
new file mode 100644
index 00000000..f0c2e76c
--- /dev/null
+++ b/Src/Plugins/General/gen_tray/gen_tray.rc
@@ -0,0 +1,178 @@
+// 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
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_DIALOG1 DIALOGEX 0, 0, 215, 212
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Nullsoft Notification Area Control Preferences"
+FONT 8, "MS Shell Dlg", 0, 0, 0x0
+BEGIN
+ CONTROL "Enable Nullsoft Notification Area Control",IDC_ONOFF,
+ "Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,4,4,207,10
+ CONTROL "",IDC_PREV,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,12,18,199,10
+ CONTROL "",IDC_PREV2,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,12,32,199,10
+ CONTROL "",IDC_PREV3,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,12,45,199,10
+ CONTROL "",IDC_PREV4,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,12,58,199,10
+ CONTROL "",IDC_PREV5,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,12,72,199,10
+ CONTROL "",IDC_PREV6,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,12,85,199,10
+ CONTROL "",IDC_PREV7,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,12,98,199,10
+ CONTROL "",IDC_PREV8,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,12,111,199,10
+ GROUPBOX "Icon Pack Selection",IDC_STATIC,4,124,207,67
+ LTEXT "Select the icon pack to use instead of the default ones or select a custom option to manually specify the pack location",IDC_STATIC,10,136,195,18
+ COMBOBOX IDC_COMBO2,10,157,178,58,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ PUSHBUTTON "?",ID_INFO,192,157,14,12
+ EDITTEXT IDC_EDIT1,10,173,158,12,ES_AUTOHSCROLL
+ PUSHBUTTON "...",IDC_BUTTON1,172,173,16,12
+ CONTROL "",IDC_LINK,"Button",BS_OWNERDRAW | BS_NOTIFY | WS_TABSTOP,4,198,53,10
+ DEFPUSHBUTTON "Close",IDOK,162,195,49,13
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+ IDD_DIALOG1, DIALOG
+ BEGIN
+ LEFTMARGIN, 4
+ RIGHTMARGIN, 211
+ TOPMARGIN, 4
+ BOTTOMMARGIN, 208
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+#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
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_ICON1 ICON "icons/icon1.ico"
+IDI_ICON2 ICON "icons/icon2.ico"
+IDI_ICON3 ICON "icons/icon3.ico"
+IDI_ICON4 ICON "icons/icon4.ico"
+IDI_ICON5 ICON "icons/icon5.ico"
+IDI_ICON7 ICON "icons/icon7.ico"
+IDI_ICON8 ICON "icons/icon8.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Bitmap
+//
+
+IDB_BITMAP1 BITMAP "icons\\compact.bmp"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE
+BEGIN
+ IDS_NULLSOFT_TRAY_CONTROL "Nullsoft Notification Area Control v%s"
+ 65535 "{25B50046-5B31-418b-B77E-1B0D140D64ED}"
+END
+
+STRINGTABLE
+BEGIN
+ IDS_PREVIOUS_TRACK "Previous Track"
+ IDS_PLAY_PAUSE "Play/Pause"
+ IDS_STOP "Stop"
+ IDS_NEXT_TRACK "Next Track"
+ IDS_OPEN_FILE "Open File"
+ IDS_COMPACT_MODE "Compact Mode"
+ IDS_DECREASE_VOLUME "Decrease Volume"
+ IDS_INCREASE_VOLUME "Increase Volume"
+ IDS_HOLD_CTRL "(hold Ctrl to restart current song)"
+ IDS_HOLD_SHIFT "(hold Shift for 'stop with fadeout')"
+// IDS_WIN2K_PLUS "(only available on WinXP and up)"
+ IDS_CTRL_TO_DECREASE "(hold Ctrl to decrease faster)"
+ IDS_CTRL_TO_INCREASE "(hold Ctrl to increase faster)"
+ IDS_STOPPED_STR " [Stopped]"
+ IDS_PAUSED_STR " [Paused]"
+ IDS_DEFAULT_ICONS "Default Icons"
+END
+
+STRINGTABLE
+BEGIN
+ IDS_CUSTOM_ICON_PACK "Custom Icon Pack..."
+ IDS_CONFIG_INFO "Notification area icon packs consist of upto 9 files (1 *.icp, 7 *.ico and 1 *.bmp) \n& all of the required files need to be in the same folder to be found.\n\nThe format of the icp file is:\n\n[tray icon pack]\nico1=1.ico\nico2=2.ico\nico3=3.ico\nico4=4.ico\nico5=5.ico\nico6=my.bmp\nico7=7.ico\nico8=8.ico\n\nOrder is: Previous, Play/Pause, Stop, Next, Open, Compact Mode\n\tVolume Down and Volume Up\n\nEach line requires just the image filename to be specified.\nThe plug-in then looks for them in the same folder as the icp file.\n\nThe 'ico6' entry provides the image for the compact mode icon and is\nmade up of 6 8x8 pixel blocks which are merged together as needed\nto form the final 16x16 icon. For transparent areas you will need to\nset the required areas in your bitmap to pink (RGB 255,0,255).\n\nThe default icon pack location is:\n%s\\Plugins\\Tray_Control"
+ IDS_OFD_FILTER_STR "Notification area icon pack (*.icp)"
+ IDS_OFD_TITLE_STR "Choose a notification area icon pack to use..."
+ IDS_GET_ICON_PACKS "Get Icon Packs"
+ IDS_DO_YOU_ALSO_WANT_TO_REMOVE_SETTINGS
+ "Do you also want to remove the saved settings for this plug-in?"
+END
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+#include "version.rc2"
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/Src/Plugins/General/gen_tray/icons/compact.bmp b/Src/Plugins/General/gen_tray/icons/compact.bmp
new file mode 100644
index 00000000..be7da86f
--- /dev/null
+++ b/Src/Plugins/General/gen_tray/icons/compact.bmp
Binary files differ
diff --git a/Src/Plugins/General/gen_tray/icons/icon1.ico b/Src/Plugins/General/gen_tray/icons/icon1.ico
new file mode 100644
index 00000000..37231154
--- /dev/null
+++ b/Src/Plugins/General/gen_tray/icons/icon1.ico
Binary files differ
diff --git a/Src/Plugins/General/gen_tray/icons/icon2.ico b/Src/Plugins/General/gen_tray/icons/icon2.ico
new file mode 100644
index 00000000..9dd35686
--- /dev/null
+++ b/Src/Plugins/General/gen_tray/icons/icon2.ico
Binary files differ
diff --git a/Src/Plugins/General/gen_tray/icons/icon3.ico b/Src/Plugins/General/gen_tray/icons/icon3.ico
new file mode 100644
index 00000000..61f36238
--- /dev/null
+++ b/Src/Plugins/General/gen_tray/icons/icon3.ico
Binary files differ
diff --git a/Src/Plugins/General/gen_tray/icons/icon4.ico b/Src/Plugins/General/gen_tray/icons/icon4.ico
new file mode 100644
index 00000000..e1a15db9
--- /dev/null
+++ b/Src/Plugins/General/gen_tray/icons/icon4.ico
Binary files differ
diff --git a/Src/Plugins/General/gen_tray/icons/icon5.ico b/Src/Plugins/General/gen_tray/icons/icon5.ico
new file mode 100644
index 00000000..f249ad0c
--- /dev/null
+++ b/Src/Plugins/General/gen_tray/icons/icon5.ico
Binary files differ
diff --git a/Src/Plugins/General/gen_tray/icons/icon7.ico b/Src/Plugins/General/gen_tray/icons/icon7.ico
new file mode 100644
index 00000000..0e2fe7ba
--- /dev/null
+++ b/Src/Plugins/General/gen_tray/icons/icon7.ico
Binary files differ
diff --git a/Src/Plugins/General/gen_tray/icons/icon8.ico b/Src/Plugins/General/gen_tray/icons/icon8.ico
new file mode 100644
index 00000000..c18da079
--- /dev/null
+++ b/Src/Plugins/General/gen_tray/icons/icon8.ico
Binary files differ
diff --git a/Src/Plugins/General/gen_tray/icons/icon9.ico b/Src/Plugins/General/gen_tray/icons/icon9.ico
new file mode 100644
index 00000000..7845f62f
--- /dev/null
+++ b/Src/Plugins/General/gen_tray/icons/icon9.ico
Binary files differ
diff --git a/Src/Plugins/General/gen_tray/version.rc2 b/Src/Plugins/General/gen_tray/version.rc2
new file mode 100644
index 00000000..5672adb0
--- /dev/null
+++ b/Src/Plugins/General/gen_tray/version.rc2
@@ -0,0 +1,39 @@
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+#include "..\..\..\Winamp/buildType.h"
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 2,49,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 General Purpose Plug-in"
+ VALUE "FileVersion", "2,49,0,0"
+ VALUE "InternalName", "Nullsoft Notification Area Control"
+ VALUE "LegalCopyright", "Copyright © 1997-2023 Winamp SA"
+ VALUE "LegalTrademarks", "Nullsoft and Winamp are trademarks of Winamp SA"
+ VALUE "OriginalFilename", "gen_tray.dll"
+ VALUE "ProductName", "Winamp"
+ VALUE "ProductVersion", STR_WINAMP_PRODUCTVER
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END